package com.alibaba.citrus.cr.forecast.facade.service;

import com.alibaba.citrus.cr.common.annotation.EpochTransactional;
import com.alibaba.citrus.cr.common.annotation.FacadeInvoker;
import com.alibaba.citrus.cr.common.enums.ordercenter.InnerMessageEventEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.OrderChannelEnum;
import com.alibaba.citrus.cr.common.exception.FacadeException;
import com.alibaba.citrus.cr.common.exception.FunctionException;
import com.alibaba.citrus.cr.common.lock.RedisLock;
import com.alibaba.citrus.cr.common.log.ModuleEnum;
import com.alibaba.citrus.cr.common.model.ApiContext;
import com.alibaba.citrus.cr.common.util.CalendarCompareUtil;
import com.alibaba.citrus.cr.forecast.common.DateUtils;
import com.alibaba.citrus.cr.forecast.common.LogUtils;
import com.alibaba.citrus.cr.forecast.functions.forecastorder.ability.ForecastOrderLineAbility;
import com.alibaba.citrus.cr.forecast.functions.forecastorder.ability.PriceQueryUtils;
import com.alibaba.citrus.cr.forecast.functions.forecastorder.ability.ScanQueue;
import com.alibaba.citrus.cr.forecast.functions.forecastorder.ability.StrategyCalculate;
import com.alibaba.citrus.cr.forecast.functions.forecastorder.constants.ForecastConstants;
import com.alibaba.citrus.cr.forecast.functions.forecastorder.entity.ForecastOrderEntity;
import com.alibaba.citrus.cr.forecast.functions.forecastorder.entity.ForecastOrderLineEntity;
import com.alibaba.citrus.cr.forecast.functions.forecastorder.factory.ForecastOrderFactory;
import com.alibaba.citrus.cr.forecast.functions.forecastorder.factory.ForecastOrderLineFactory;
import com.alibaba.cloud.retail.customer.center.ability.ConfigurationAbilityService;
import com.alibaba.cloud.retail.customer.center.ability.ShipToPartyAbilityService;
import com.alibaba.citrus.cr.forecast.repository.*;
import com.alibaba.cloud.retail.customer.center.req.ShipToPartyAccurateQueryReq;
import com.alibaba.cloud.retail.customer.center.req.configuration.ConfigurationOptionReq;
import com.alibaba.cloud.retail.customer.center.resp.ShipToPartyInternalResp;
import com.alibaba.cloud.retail.customer.center.resp.option.ConfigurationOptionResp;
import com.alibaba.cz.base.model.enterprise.EmployeeSDO;
import com.alibaba.cz.base.tool.Nullable;
import com.alibaba.cz.base.tool.UUIDUtil;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.log.model.OpLogModel;
import com.alibaba.cz.base.tool.log.model.OperatorType;
import com.alibaba.cz.base.tool.message.ErrorMessage;
import com.alibaba.cz.base.tool.page.PageResult;
import com.alibaba.cz.enterprise.api.model.employee.EmployeeBatchQueryRequest;
import com.alibaba.cz.enterprise.api.service.EmployeeService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.db.service.CustomSequenceAccessor;
import com.alibaba.lattice2.epoch.middleware.mq.runtime.EpochMessageService;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.alibaba.lattice2.epoch.user.dto.LoginUser;
import com.alibaba.lattice2.epoch.user.service.EpochLoginUserService;
import com.epoch.app.bcorder.contants.BcOrderConstants;
import com.epoch.app.bcorder.esdegrade.dto.GetEsDegradeValueResponse;
import com.epoch.app.bcorder.esdegrade.service.EsDegradeService;
import com.epoch.app.bcorder.model.dto.ScItemSDO;
import com.epoch.app.bcorder.model.dto.*;
import com.epoch.app.bcorder.platform_enhance.SaleOrderTag;
import com.epoch.app.bcorder.service.BaseDataService;
import com.epoch.app.bcorder.service.BcOrderService;
import com.epoch.app.bcorder.service.UnifiedInventoryService;
import com.epoch.app.crb2btradecenter.api.orderquery.dto.QuerySingleRequest;
import com.epoch.app.crb2btradecenter.api.orderquery.service.OrderQueryService;
import com.epoch.app.crb2btradecenter.api.orderwrite.service.OrderWriteService;
import com.epoch.app.crb2btradecenter.dto.request.SaveSaleOrderRequest;
import com.epoch.app.crb2btradecenter.dto.response.BatchCreateOrderResponse;
import com.epoch.app.crb2btradecenter.messagetask.dto.CreateResponse;
import com.epoch.app.crb2btradecenter.messagetask.model.MessageTask;
import com.epoch.app.crb2btradecenter.messagetask.service.MessageTaskService;
import com.epoch.app.crb2btradecenter.model.dto.TradeMessageSDO;
import com.epoch.app.crb2btradecenter.model.enums.MessageTaskTypeEnum;
import com.epoch.app.crb2btradecenter.sdo.OrderLineSDO;
import com.epoch.app.crb2btradecenter.sdo.OrderSDO;
import com.epoch.app.crforecastsales.api.forecastorderlinequery.dto.CountRefuseLineRequest;
import com.epoch.app.crforecastsales.api.forecastorderlinequery.dto.CountRefuseLineResponse;
import com.epoch.app.crforecastsales.api.forecastorderlinequery.service.ForecastOrderLineQueryService;
import com.epoch.app.crforecastsales.api.forecastorderwrite.dto.DeleteActivityForecastRequest;
import com.epoch.app.crforecastsales.api.forecastorderwrite.dto.*;
import com.epoch.app.crforecastsales.api.forecastorderwrite.service.ForecastOrderWriteService;
import com.epoch.app.crforecastsales.domian.forecastorder.dto.BatchQueryForecastByBizNoResponse;
import com.epoch.app.crforecastsales.domian.forecastorder.dto.QueryBySourceNoRequest;
import com.epoch.app.crforecastsales.domian.forecastorder.model.ForecastOrder;
import com.epoch.app.crforecastsales.domian.forecastorder.service.ForecastOrderService;
import com.epoch.app.crforecastsales.domian.forecastorderline.dto.BatchLoadListRequest;
import com.epoch.app.crforecastsales.domian.forecastorderline.dto.BatchLoadListResponse;
import com.epoch.app.crforecastsales.domian.forecastorderline.dto.UpdateCollectStatusRequest;
import com.epoch.app.crforecastsales.domian.forecastorderline.model.ForecastOrderLine;
import com.epoch.app.crforecastsales.domian.forecastorderline.service.ForecastOrderLineService;
import com.epoch.app.crforecastsales.dto.request.CancelForecastOrderRequest;
import com.epoch.app.crforecastsales.dto.request.ForecastOrderExportRequest;
import com.epoch.app.crforecastsales.dto.request.*;
import com.epoch.app.crforecastsales.dto.response.*;
import com.epoch.app.crforecastsales.enums.ForecastStatusEnum;
import com.epoch.app.crforecastsales.failorder.service.FailOrderService;
import com.epoch.app.crforecastsales.model.dto.*;
import com.epoch.app.crforecastsales.model.dto.UpdateForInnerForecastRequest;
import com.epoch.app.crforecastsales.model.enums.ForecastDealStatusSEO;
import com.epoch.app.crforecastsales.model.enums.ForecastDealTypeSEO;
import com.epoch.app.crforecastsales.model.enums.ForecastOrderLogEnum;
import com.epoch.app.crforecastsales.model.enums.ItemGroupEnum;
import com.epoch.app.crforecastsales.sdo.ForecastOrderLineSDO;
import com.epoch.app.crforecastsales.sdo.ForecastOrderSDO;
import com.epoch.app.crforecastsales.sdo.MainOrderInfo;
import com.epoch.app.crforecastsales.service.CrForecastSalesService;
import com.epoch.app.crplatformenhance.api.customeraddressquery.service.CustomerAddressQueryService;
import com.epoch.app.crplatformenhance.api.customerquery.service.CustomerQueryService;
import com.epoch.app.crplatformenhance.api.group.scitemgroupquery.service.ScItemGroupQueryService;
import com.epoch.app.crplatformenhance.api.organizationquery.service.OrganizationQueryService;
import com.epoch.app.crplatformenhance.api.scitemquery.service.ScItemQueryService;
import com.epoch.app.crplatformenhance.api.strategyquery.service.StrategyQueryService;
import com.epoch.app.crplatformenhance.channel.service.ChannelService;
import com.epoch.app.crplatformenhance.dictionaryquery.service.DictionaryQueryService;
import com.epoch.app.crplatformenhance.domain.scitemunit.dto.ScItemUnitLoadListRequest;
import com.epoch.app.crplatformenhance.domain.scitemunit.model.ScItemUnit;
import com.epoch.app.crplatformenhance.domain.scitemunit.service.ScItemUnitService;
import com.epoch.app.crplatformenhance.dto.request.CustomerAddressBatchRequest;
import com.epoch.app.crplatformenhance.dto.request.CustomerAddressRequest;
import com.epoch.app.crplatformenhance.dto.request.CustomerRequest;
import com.epoch.app.crplatformenhance.dto.request.QueryScItemGroupRequest;
import com.epoch.app.crplatformenhance.dto.response.ScItemGroupResponse;
import com.epoch.app.crplatformenhance.enums.OrganizationTypeEnum;
import com.epoch.app.crplatformenhance.enums.StrategyTypeEnum;
import com.epoch.app.crplatformenhance.inventoryallotquery.service.InventoryAllotQueryService;
import com.epoch.app.crplatformenhance.model.dto.*;
import com.epoch.app.crplatformenhance.model.enums.RuleTypeEnum;
import com.epoch.app.crplatformenhance.model.enums.ScItemManageRangeStatus;
import com.epoch.app.crplatformenhance.scitemmanagerange.model.ScItemManageRange;
import com.epoch.app.crplatformenhance.scitemmanagerangeread.service.ScItemManageRangeReadService;
import com.epoch.app.crplatformenhance.sdo.CustomerAddressSDO;
import com.epoch.app.crplatformenhance.sdo.OrganizationSDO;
import com.epoch.app.crplatformenhance.sdo.*;
import com.epoch.app.crplatformenhance.service.CrPlatformEnhanceService;
import com.epoch.app.crpricecenter.api.activityquery.service.ActivityQueryService;
import com.epoch.app.crpricecenter.dto.request.ActivityInfoRequest;
import com.epoch.app.crpricecenter.dto.request.ActivityItemInfoRequest;
import com.epoch.app.crpricecenter.dto.response.ActivityInfoResponse;
import com.epoch.app.crpricecenter.model.dto.ActivityResponse;
import com.epoch.app.crpricecenter.model.dto.QueryActivityRequest;
import com.epoch.app.crunifiedinventory.api.allocaterelationread.dto.QueryAllocateRelationForOrderRequest;
import com.epoch.app.crunifiedinventory.api.allocaterelationread.service.AllocateRelationReadService;
import com.epoch.app.crunifiedinventory.model.dto.ForecastAnalysisInventoryRequest;
import com.epoch.app.crunifiedinventory.model.dto.ForecastAnalysisQueryInventoryRequest;
import com.epoch.app.crunifiedinventory.sdo.AllocateRelationSDO;
import com.epoch.app.crunifiedinventory.sdo.enums.DocumentReasonEnum;
import com.epoch.app.crunifiedinventory.sdo.enums.TransportModeEnum;
import com.epoch.app.crunifiedinventory.service.CrUnifiedInventoryService;
import com.epoch.app.mnordercenter.forecastorderbiz.model.ForecastOrderBiz;
import com.epoch.app.mnordercenter.forecastorderbiz.service.ForecastOrderBizService;
import com.epoch.app.mnordercenter.model.dto.*;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Primary;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;


@Service
@Primary
public class ForecastOrderWriteServiceImpl implements ForecastOrderWriteService {
    public static final String ANALYZE_BATCH_NO = "analysisBatchNo";
    public static final String ANALYZE_TYPE = "type";
    public static final String ANALYZE_USER_NO = "analysisUserNo";
    public static final String ANALYZE_ORDER_LINE_IDS = "ids";
    public static final String ANALYZE_API_CONTEXT = "apiContext";
    public static final String ANALYZE_MESSAGE_CODE = "forecast_order_analysis_message";
    public static final String ANALYZE_MESSAGE_TOPIC = "CR_FORECAST_ANALYSIS_V2";
    public static final String ANALYZE_MESSAGE_TAG = "forecastAnalysis";
    private static final String ONLY_JOIN_WITHOUT_ACTIVITY = "onlyJoinWithoutActivity";
    private static Integer pageSize = 2000;

    //前端页面传入参数，与前端协商确定
    public static final String AUTO_CREATE_SALE_ORDER_FLAG = "joinAndHandle";
    //能确认生产销售单的预报单据状态
    public static final List<Integer> CAN_CONFIRM_FORECAST_STATUS = Lists.newArrayList(ForecastStatusEnum.WAITING_FOR_REPLY.getNumValue(),ForecastStatusEnum.PARTIAL_REPLY.getNumValue());
    //能确认生产销售单的预报单据处理状态
    public static final List<Integer> CAN_CONFIRM_FORECAST_DEAL_STATUS = Lists.newArrayList(ForecastDealStatusSEO.WAITING_DEAL.getStatus(),ForecastDealStatusSEO.CONFIRM_ED.getStatus(),ForecastDealStatusSEO.ANALYSIS_ED.getStatus(),ForecastDealStatusSEO.CHECk_ING.getStatus(),ForecastDealStatusSEO.CHECk_ED.getStatus());
    @Resource
    ForecastOrderLineAbility forecastOrderLineAbility;
    @Resource
    private ForecastOrderWriteRepository forecastOrderWriteRepository;
    @Resource
    private ForecastOrderQueryRepository forecastOrderQueryRepository;
    @Resource
    private ForecastOrderLineQueryService forecastOrderLineQueryService;
    @Resource
    ForecastOrderLineWriteRepository forecastOrderLineWriteRepository;
    @Resource
    ForecastOrderLineQueryRepository forecastOrderLineQueryRepository;
    @Resource
    DealLineQueryRepository dealLineQueryRepository;
    @Resource
    DealLineWriteRepository dealLineWriteRepository;
    @Resource
    CustomerAddressQueryService customerAddressQueryService;
    @Resource
    ScItemQueryService scItemQueryService;
    @Resource
    ScanQueue scanQueue;
    @Resource
    StrategyCalculate StrategyCalculate;
    @Autowired
    ScItemGroupQueryService scItemGroupQueryService;
    @Autowired
    CustomerQueryService customerQueryService;
    @Autowired
    OrganizationQueryService organizationQueryService;
    @Autowired
    ChannelService channelService;
    @Autowired
    CustomSequenceAccessor customSequenceAccessor;
    @Resource
    BaseDataService baseDataService;
    @Resource
    UnifiedInventoryService unifiedInventoryService;
    @Resource
    DictionaryQueryService dictionaryQueryService;
    @Resource
    ActivityQueryService activityQueryService;
    @Resource
    ScItemUnitService scItemUnitService;
    @Resource
    OrderWriteService orderWriteService;
    @Resource
    private OrderQueryService orderQueryService;
    @Resource
    FailOrderService failOrderService;
    @Resource
    private InventoryAllotQueryService inventoryAllotQueryService;
    @Resource
    private StrategyQueryService strategyQueryService;
    @Resource
    private MessageTaskService messageTaskService;

    @Resource(name = "scItemsQueryTaskExecutor")
    private ThreadPoolTaskExecutor scItemsQueryTaskExecutor;
    @Resource(name = "forecastSaleTaskExecutor")
    private ThreadPoolTaskExecutor forecastSaleTaskExecutor;

    @Resource
    private PriceQueryUtils priceQueryUtils;
    @Resource
    private EpochMessageService messageService;
    @Resource
    private CrForecastSalesService crForecastSalesService;

    @Resource
    private CrPlatformEnhanceService crPlatformEnhanceService;
    @Resource
    private AllocateRelationReadService allocateRelationReadService;
    @Resource
    private BcOrderService bcOrderService;

    @Resource
    private EpochLoginUserService epochLoginUserService;

    @Resource
    private ApplicationContext applicationContext;

    @Resource
    private ForecastOrderService forecastOrderService;

    @Autowired
    private EsDegradeService esDegradeService;

    @Autowired
    private CrUnifiedInventoryService crUnifiedInventoryService;
    @Resource
    private ScItemManageRangeReadService scItemManageRangeReadService;
    @Resource
    private ForecastOrderLineService forecastOrderLineService;
    @DubboReference
    private ShipToPartyAbilityService shipToPartyAbilityService;

    @Resource
    private ForecastOrderBizService forecastBizService;

    @DubboReference
    private EmployeeService employeeService;

    @DubboReference
    private ConfigurationAbilityService configurationAbilityService;


    private static final Log log = Log.getLogger(ForecastOrderWriteServiceImpl.class);

    @Override
    @FacadeInvoker
    @EpochTransactional(appCode = "cr_forecast_sales", dataSourceCode = "cr_ots")
    public Result<CreateForecastOrderReponse> createForecastOrder(CreateForecastOrderRequest createForecastOrderRequest) {
        log.info("预报订单创建或修改入参 = {}", JSONObject.toJSONString(createForecastOrderRequest));
        // 构造返回值 返回结果封装
        CreateForecastOrderReponse saveForecastOrderReponse = new CreateForecastOrderReponse();
        ArrayList<String> orderIdList = new ArrayList<>();
        //  工程构造entity
        List<ForecastOrderEntity> forecastOrderList = ForecastOrderFactory.createDraft(createForecastOrderRequest);
        // 保存预报订单
        for (ForecastOrderEntity forecastOrderEntity : forecastOrderList) {
            String id="";
            /* ForecastOrderSDO forecastOrderSDO = forecastOrderEntity.getForecastOrderSDO();
            BaselineGetOrganizationByIds2Request baselineGetOrganizationByIdsRequest = new BaselineGetOrganizationByIds2Request();
            baselineGetOrganizationByIdsRequest.setIds(Collections.singletonList(forecastOrderSDO.getOrganizationCode()));
            BaselineGetOrganizationByIds2Response organization = baseDataService.baselineGetOrganizationByIds2(baselineGetOrganizationByIdsRequest);
            if (Objects.nonNull(organization)&&CollectionUtils.isNotEmpty(organization.getResult())&&organization.getResult().get(0).getCode().equals("6136")){
                id = omniConvert(forecastOrderSDO);
                orderIdList.add(id);
                continue;
            } */
            id = forecastOrderEntity.save();
            orderIdList.add(id);
        }
        saveForecastOrderReponse.setOrderIds(orderIdList);
        return Result.success(saveForecastOrderReponse);
    }

    private String omniConvert(ForecastOrderSDO forecastOrderSDO) {
        String orderId="";
        ForecastOrderBizCreateRequest forecastOrderBizCreateRequest = new ForecastOrderBizCreateRequest();

        forecastOrderBizCreateRequest.setFromSys("APP_OMNI");
        forecastOrderBizCreateRequest.setBusinessType("11");
        forecastOrderBizCreateRequest.setBusinessUnitCode("6136");
        CreateForecastDTO createForecastDTO = new CreateForecastDTO();
        // 是否提交
        createForecastDTO.setSubmitFlag(String.valueOf(Boolean.FALSE));
        // 来源单号
        String nextStringSequence = "M"+customSequenceAccessor.getNextStringSequence("cr_forecast_sales", "forecastOrderId");

        createForecastDTO.setSourceOrderNo(nextStringSequence);
        // 订单类型
        createForecastDTO.setSalesOrderType("ZQT2");
        // 订单渠道编码
        createForecastDTO.setOrderChannelCode(OrderChannelEnum.COMPANY.getCode());
        // 客户
        createForecastDTO.setCustomerCode(forecastOrderSDO.getCustomerCode());


        List<String> orgIdList = new ArrayList<>();
        orgIdList.add(forecastOrderSDO.getBisUnitCode());
        orgIdList.add(forecastOrderSDO.getDepartmentCode());
        orgIdList.add(forecastOrderSDO.getOrganizationCode());
        orgIdList.add(forecastOrderSDO.getSaleChannelCode());
        BaselineGetOrganizationByIds2Request innerOrgReq = new BaselineGetOrganizationByIds2Request();
        innerOrgReq.setIds(orgIdList);
        BaselineGetOrganizationByIds2Response innerOrgResp =  baseDataService.baselineGetOrganizationByIds2(innerOrgReq);
        if (Objects.nonNull(innerOrgResp)&&CollectionUtils.isNotEmpty(innerOrgResp.getResult())){
            Map<String, com.epoch.app.bcorder.model.dto.OrganizationSDO> organizationMap = innerOrgResp.getResult().stream().collect(Collectors.toMap(com.epoch.app.bcorder.model.dto.OrganizationSDO::getId, Function.identity(), (k, v) -> k));

            // 销售组织编码
            com.epoch.app.bcorder.model.dto.OrganizationSDO organizationSDO = organizationMap.get(forecastOrderSDO.getOrganizationCode());


            if (Objects.nonNull(organizationSDO)){
                createForecastDTO.setSalesOrganizationCode(organizationSDO.getCode());
            }

            com.epoch.app.bcorder.model.dto.OrganizationSDO departmentSDO = organizationMap.get(forecastOrderSDO.getDepartmentCode());
            if (Objects.nonNull(departmentSDO)){
                // 销售部门编码
                createForecastDTO.setSalesDepartmentCode(departmentSDO.getCode());

                ConfigurationOptionReq configurationOptionReq = new ConfigurationOptionReq();
                configurationOptionReq.setType("salesGroup");
                configurationOptionReq.setCode(departmentSDO.getCode());
                log.info("CustomerCenterAdapterImpl#queryConfigurationOptionList configurationOptionReq={}", JSON.toJSONString(configurationOptionReq));
                com.alibaba.lydass.bizphin.maca.model.Result<List<ConfigurationOptionResp>> listResult = configurationAbilityService.queryConfigurationOptionList(configurationOptionReq);
                log.info("CustomerCenterAdapterImpl#queryConfigurationOptionList listResult={}", JSON.toJSONString(listResult));
                if (Objects.nonNull(listResult)&&CollectionUtils.isNotEmpty(listResult.getResult())){
                    // 销售部门名称
                    createForecastDTO.setSalesDepartmentName(listResult.getResult().get(0).getLabel());
                }

            }


            com.epoch.app.bcorder.model.dto.OrganizationSDO saleChannelSDO = organizationMap.get(forecastOrderSDO.getSaleChannelCode());
            if (Objects.nonNull(saleChannelSDO)){
                // 销售渠道编码
                createForecastDTO.setSalesChannelCode(saleChannelSDO.getCode());

                ConfigurationOptionReq configurationOptionReq = new ConfigurationOptionReq();
                configurationOptionReq.setType("salesOffice");
                configurationOptionReq.setCode(saleChannelSDO.getCode());
                log.info("CustomerCenterAdapterImpl#queryConfigurationOptionList configurationOptionReq={}", JSON.toJSONString(configurationOptionReq));
                com.alibaba.lydass.bizphin.maca.model.Result<List<ConfigurationOptionResp>> listResult = configurationAbilityService.queryConfigurationOptionList(configurationOptionReq);
                log.info("CustomerCenterAdapterImpl#queryConfigurationOptionList listResult={}", JSON.toJSONString(listResult));
                if (Objects.nonNull(listResult)&&CollectionUtils.isNotEmpty(listResult.getResult())){
                    // 销售渠道名称
                    createForecastDTO.setSalesChannelName(listResult.getResult().get(0).getLabel());
                }

            }

        }


        // 业务渠道编码
        createForecastDTO.setBusinessChannel(forecastOrderSDO.getChannelCode());
        // 产品组
        createForecastDTO.setProductGroupCode(forecastOrderSDO.getProductGroupCode());
        // 客户采购订单号
        createForecastDTO.setCustomerPurchaseOrderNo(forecastOrderSDO.getCustomerReferenceNo());
        // 期望交货日期

        if (Objects.nonNull(forecastOrderSDO.getCustomerExpectTDate())){

            createForecastDTO.setExpectedDeliveryDate(DateUtils.formatDate(forecastOrderSDO.getCustomerExpectTDate(),DateUtils.PATTEN_YMD));
        }


        // 发货仓库编码
        QueryWarehouseByIdRequest queryWarehouseByIdRequest = new QueryWarehouseByIdRequest();
        queryWarehouseByIdRequest.setId(forecastOrderSDO.getWareHouseCode());
        Result<WarehouseInfo> warehouseInfoResult = unifiedInventoryService.queryWarehouseById(queryWarehouseByIdRequest);
        if (Objects.nonNull(warehouseInfoResult)&&Objects.nonNull(warehouseInfoResult.getResult())){
            createForecastDTO.setShippingWarehouseCode(warehouseInfoResult.getResult().getCode());
        }
        // 创建人
        EmployeeBatchQueryRequest batchQueryRequest = new EmployeeBatchQueryRequest();
        batchQueryRequest.setIdList(Collections.singletonList(forecastOrderSDO.getCreatorId()));
        com.alibaba.cz.base.tool.result.Result<List<EmployeeSDO>> listResult = employeeService.batchQueryEmployeeByCondition(batchQueryRequest);
        if (Objects.nonNull(listResult)&&CollectionUtils.isNotEmpty(listResult.getResult())){
            createForecastDTO.setCreatorCode(listResult.getResult().get(0).getWorkId());
        }

        // 客户送达方编码
        createForecastDTO.setShipToPartyCode(forecastOrderSDO.getReceiveAddressCode());
        // 配送方式
        createForecastDTO.setDeliveryMethodCode(forecastOrderSDO.getTransportModeCode());
        // 备注
        createForecastDTO.setNote(forecastOrderSDO.getRemark());

        List<ShipToPartyAccurateQueryReq> reqList = new ArrayList<>();
        ShipToPartyAccurateQueryReq req = new ShipToPartyAccurateQueryReq();
        req.setShipToPartyCode(createForecastDTO.getShipToPartyCode());
        req.setBusinessType(forecastOrderBizCreateRequest.getBusinessType());
        req.setSoldToPartyCode(createForecastDTO.getCustomerCode());
        req.setSalesChannelCode(createForecastDTO.getSalesChannelCode());
        req.setSalesOrganizationCode(createForecastDTO.getSalesOrganizationCode());
        com.alibaba.lydass.bizphin.maca.model.Result<List<ShipToPartyInternalResp>> shipToPartyList = shipToPartyAbilityService.queryShipToPartyList(reqList);
        log.info("送达方查询 request={}, result={}", JSONArray.toJSONString(reqList), JSONObject.toJSONString(listResult));
        if (Objects.nonNull(shipToPartyList)&&CollectionUtils.isNotEmpty(shipToPartyList.getResult())){
//            createForecastDTO.setShipToPartyName(shipToPartyList.getResult().get(0).getShipToPartyName());
        }


        Map<String, Object> bizFeatures = new HashMap<>();
        bizFeatures.put("creditBalance", forecastOrderSDO.getCreditBalance());
        bizFeatures.put("feeBalance", forecastOrderSDO.getFeeBalance());
//                bizFeatures.put(ForecastBizFeaturesEnum.TOTAL_QUANTITY.getCode(), requestDTO.getTotalQuantity());
//                bizFeatures.put(ForecastBizFeaturesEnum.TOTAL_AMOUNT.getCode(), requestDTO.getOrderTotalFee());
        bizFeatures.put("contract", forecastOrderSDO.getContact());
        bizFeatures.put("contractPhone", forecastOrderSDO.getContactPhone());
        bizFeatures.put("addressName", forecastOrderSDO.getAddressName());
//                bizFeatures.put(ForecastBizFeaturesEnum.DEADLINE.getCode(), requestDTO.getDeadline());
        // 扩展字段
        createForecastDTO.setBizFeatures(JSONObject.toJSONString(bizFeatures));

        List<ForecastOrderLineSDO> forecastOrderLineSDOList = forecastOrderSDO.getForecastOrderLineSDOList();
        List<CreateForecastDetailDTO> forecastOrderDetailDTOS=new ArrayList<>();
        if (CollectionUtils.isNotEmpty(forecastOrderLineSDOList)) {
            for (int i = 0; i < forecastOrderLineSDOList.size(); i++) {
                ForecastOrderLineSDO createForecastDetailRequestDTO = forecastOrderLineSDOList.get(i);
                CreateForecastDetailDTO createForecastDetailDTO=new CreateForecastDetailDTO();
                // 来源单行号
                createForecastDetailDTO.setSourceLineNum(String.valueOf((i + 1) * 10));
                // 发货仓库
                createForecastDetailDTO.setShippingWarehouseCode(createForecastDTO.getShippingWarehouseCode());
                // 拓展字段
                createForecastDetailDTO.setProductCode(createForecastDetailRequestDTO.getGoodsCode());
                createForecastDetailDTO.setNote(createForecastDetailRequestDTO.getDetailRemark());
                createForecastDetailDTO.setProductQuantity(createForecastDetailRequestDTO.getQuantity());
                createForecastDetailDTO.setSalesUnitCode(createForecastDetailRequestDTO.getSaleUnitCode());

                Map<String, Object> detailBizFeatures = StringUtils.isNotBlank(createForecastDetailRequestDTO.getBizFeatures())?JSONObject.parseObject(createForecastDetailRequestDTO.getBizFeatures(), Map.class): new HashMap<>();
//                        detailBizFeatures.put(ForecastBizFeaturesEnum.BARCODE.getCode(), createForecastDetailRequestDTO.getBarCode());

                createForecastDetailDTO.setBizFeatures(JSONObject.toJSONString(detailBizFeatures));
                forecastOrderDetailDTOS.add(createForecastDetailDTO);
            }
        }
        createForecastDTO.setForecastOrderDetailDTOS(forecastOrderDetailDTOS);
        forecastOrderBizCreateRequest.setCreateForecastOrderDTO(createForecastDTO);
        forecastOrderBizCreateRequest.setReqNo(nextStringSequence);
        Result<ForecastBizSyncResponse> forecastBizSyncResponseResult = forecastBizService.create(forecastOrderBizCreateRequest);
        if (!forecastBizSyncResponseResult.isSuccess()){
            log.error("创建预报单失败,请求参数:{},返回结果:{}", JSONObject.toJSONString(forecastOrderBizCreateRequest), JSONObject.toJSONString(forecastBizSyncResponseResult));
            throw new FacadeException(forecastBizSyncResponseResult.getErrorCode());
        }
        String salesOrderNo = forecastBizSyncResponseResult.getResult().getSalesOrderNo();
        QueryBySourceNoRequest queryBySourceNoRequest = new QueryBySourceNoRequest();
        queryBySourceNoRequest.setOrderBizId(salesOrderNo);
        queryBySourceNoRequest.setFromSys(forecastOrderBizCreateRequest.getFromSys());
        queryBySourceNoRequest.setBusinessTypeCode(forecastOrderBizCreateRequest.getBusinessType());
        queryBySourceNoRequest.setUnitCode(forecastOrderBizCreateRequest.getBusinessUnitCode());
        Result<ForecastOrder> forecastOrderResult = null;
        try {
            forecastOrderResult = forecastOrderService.queryBySourceNo(queryBySourceNoRequest);
        } catch (Exception e) {
            log.error("查询预报单失败,请求参数:{},返回结果:{}", JSONObject.toJSONString(queryBySourceNoRequest), JSONObject.toJSONString(forecastOrderResult));
            e.printStackTrace();
            throw new FacadeException("查询预报单失败{}",salesOrderNo);
        }
        if (Objects.nonNull(forecastOrderResult)&&Objects.nonNull(forecastOrderResult.getResult())){
            return String.valueOf(forecastOrderResult.getResult().getId());
        }

        return orderId;
    }

    /*
        更改预报单保存草稿 王成
     */
    @Override
    @FacadeInvoker
    public Result<ModifyForecastOrderReponse> modifyForecastOrder(ModifyForecastOrderRequest modifyForecastOrderRequest) {
        LoginUser loginUser = epochLoginUserService.getLoginUser();
        log.info("预报订单修改入参= {}", JSONObject.toJSONString(modifyForecastOrderRequest));
        //list入参怎么办
        Integer count = 0;
        // 构造返回值 返回结果封装
        ModifyForecastOrderReponse modifyForecastOrderReponse = new ModifyForecastOrderReponse();
        //  工程构造entity
        List<ForecastOrderEntity> forecastOrderList = ForecastOrderFactory.modifyDraft(modifyForecastOrderRequest);
        // 保存预报订单
        for (ForecastOrderEntity forecastOrderEntity : forecastOrderList) {
            Integer count1 = forecastOrderEntity.modify();
            LogUtils.printOperateLog(forecastOrderEntity.getForecastOrderSDO(), ForecastOrderLogEnum.EDIT.getForecastOrderLogValue(), "编辑预报订单", loginUser);
            count += count1;
        }
        modifyForecastOrderReponse.setCount(count);
        return Result.success(modifyForecastOrderReponse);
    }

    @Override
    @FacadeInvoker
    public Result<ModifyForecastInfoResponse> modifyForecastOrderInfo(UpdateForInnerForecastRequest request) {
        if (StringUtils.isBlank(request.getSalesOrderNo())) return Result.fail("OC-04-003-01-16-009", "预报订单单号不能为空");
        BatchQueryForecastByBizNoResponse forecastByBizNoResponse = forecastOrderQueryRepository.batchQueryForecastByBizNo(Collections.singletonList(request.getSalesOrderNo()));

        if (Objects.isNull(forecastByBizNoResponse) || CollectionUtils.isEmpty(forecastByBizNoResponse.getResult())) {
            return Result.fail("OC-04-003-01-16-009", "预报订单查询失败");
        }

        List<ForecastOrder> forecastOrderList = forecastByBizNoResponse.getResult();
        ForecastOrder forecastOrder = forecastOrderList.get(0);

        ForecastOrderSDO forecastOrderSDORequest = new ForecastOrderSDO();
        forecastOrderSDORequest.setBusinessUnitCode(request.getBusinessUnitCode());
        forecastOrderSDORequest.setBusinessUnitName(request.getBusinessUnitName());

        forecastOrderSDORequest.setSalesOrganizationCode(request.getSalesOrganizationCode());
        forecastOrderSDORequest.setSalesOrganizationName(request.getSalesOrganizationName());
        forecastOrderSDORequest.setBusinessType(request.getBusinessType());
        forecastOrderSDORequest.setBusinessTypeName(request.getBusinessTypeName());
        forecastOrderSDORequest.setProductGroupCode(request.getBusinessType());
        forecastOrderSDORequest.setProductGroupName(request.getBusinessTypeName());
        forecastOrderSDORequest.setChannelCode(request.getBusinessChannelCode());
        forecastOrderSDORequest.setChannelName(request.getBusinessChannelName());
        forecastOrderSDORequest.setCustomerName(request.getSoldToPartyName());
        forecastOrderSDORequest.setCustomerCode(request.getSoldToPartyCode());
        forecastOrderSDORequest.setShipToPartyCode(request.getShipToPartyCode());
        forecastOrderSDORequest.setShipToPartyName(request.getShipToPartyName());


        forecastOrderSDORequest.setSaleChannelCode(request.getSalesChannelCode());
        forecastOrderSDORequest.setSaleChannelName(request.getSalesChannelName());
        forecastOrderSDORequest.setSalesDepartmentCode(request.getSalesDepartmentCode());
        forecastOrderSDORequest.setSalesDepartmentName(request.getSalesDepartmentName());
        forecastOrderSDORequest.setCustomerGroup(request.getCustomerGroupCode());
        forecastOrderSDORequest.setCustomerGroupName(request.getCustomerGroupName());

        forecastOrderSDORequest.setCreateReason(request.getCreateReason());
        forecastOrderSDORequest.setFromSys(request.getFromSys());
        forecastOrderSDORequest.setOrderCategoryCode(request.getOrderCategoryCode());
        forecastOrderSDORequest.setOrderChannelCode(request.getOrderChannelCode());
        forecastOrderSDORequest.setCustomerPurchaseOrderNo(request.getCustomerPurchaseOrderNo());
        forecastOrderSDORequest.setId(String.valueOf(forecastOrder.getId()));
//        forecastOrderSDORequest.setShipToPartyName(request.getShipToPartyName());

        ForecastOrderLineSDO pageQueryForecastRequest = new ForecastOrderLineSDO();
        if (CollectionUtils.isNotEmpty(request.getDetailList())){
            Map<String, UpdateForInnerForecastDetailRequest> requestLineMap = request.getDetailList().stream().collect(Collectors.toMap(UpdateForInnerForecastDetailRequest::getLineNum, Function.identity(), (o1, o2) -> o1));
            pageQueryForecastRequest.setMainOrderId(String.valueOf(forecastOrder.getId()));
            pageQueryForecastRequest.setStart(0);
            pageQueryForecastRequest.setLimit(100);
            List<ForecastOrderLineSDO> pageQueryOrderLine = forecastOrderLineQueryRepository.queyrLineDetailList(pageQueryForecastRequest);
            if ( CollectionUtils.isNotEmpty(pageQueryOrderLine)) {
                List<ForecastOrderLineSDO> lineResponseList = pageQueryOrderLine.stream().filter(o -> requestLineMap.containsKey(o.getSerialNumber())).collect(Collectors.toList());

                for (ForecastOrderLineSDO queryForecastLineResponse : lineResponseList) {
                    UpdateForInnerForecastDetailRequest line = requestLineMap.get(queryForecastLineResponse.getSerialNumber());

                    ForecastOrderLineSDO forecastOrderLineSDO = new ForecastOrderLineSDO();
                    forecastOrderLineSDO.setDetailRemark(line.getNote());
                    forecastOrderLineSDO.setFeatures(queryForecastLineResponse.getFeatures());
                    forecastOrderLineSDO.setId(queryForecastLineResponse.getId());
                    try {
                        forecastOrderLineWriteRepository.update(forecastOrderLineSDO);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        ModifyForecastInfoResponse modifyForecastResponseDTO = new ModifyForecastInfoResponse();

        try {

            boolean isSuccess = forecastOrderWriteRepository.modifyForecast(forecastOrderSDORequest);
            modifyForecastResponseDTO.setForecastOrderBizNo(forecastOrderSDORequest.getOrderBizId());
            modifyForecastResponseDTO.setSuccess(isSuccess);
            return Result.success(modifyForecastResponseDTO, "", "");
        }catch (Exception e){
            log.error("修改预报单持久化异常", e);
            return Result.fail("OC-04-003-01-16-005", "预报订单修改失败");
        }
    }

    /*
        取消 预报单保存草稿 王成
     */
    @Override
    @FacadeInvoker
    public Result<CancelForecastOrderReponse> cancelForecastOrder(CancelForecastOrderRequest cancelForecastOrderRequest) {
        List<ForecastOrderSDO> waitReplyList=new ArrayList<>();
        LoginUser loginUser = epochLoginUserService.getLoginUser();
        log.info("预报订单取消入参 = {}", JSONObject.toJSONString(cancelForecastOrderRequest));
        // 构造返回值 返回结果封装
        CancelForecastOrderReponse cancelForecastOrderReponse = new CancelForecastOrderReponse();
        // 获取主键集合
        List<String> ids = cancelForecastOrderRequest.getIds();
        if (CollectionUtils.isEmpty(ids)) {
            return Result.fail(cancelForecastOrderReponse, "error", "id集合不能为空");
        }
        //查询订单是否存在
        List<ForecastOrderSDO> forecastOrderSDOList = forecastOrderQueryRepository.batchQueryForecastOrder(ids);
        if (CollectionUtils.isEmpty(forecastOrderSDOList)) {
            return Result.fail(cancelForecastOrderReponse, "error", "订单不存在");
        }
        //判断订单状态是待回复、草稿和待提交可以取消
        for (ForecastOrderSDO forecastOrderSDO : forecastOrderSDOList) {
            Integer status = forecastOrderSDO.getStatus();
            if (ForecastStatusEnum.of(status).equals(ForecastStatusEnum.PARTIAL_REPLY) || ForecastStatusEnum.of(status).equals(ForecastStatusEnum.COMPLETED) || ForecastStatusEnum.of(status).equals(ForecastStatusEnum.CANCELLED)) {
                return Result.fail(cancelForecastOrderReponse, "error", "订单部分回复、已完成或已取消状态，不可取消");
            }
            //待回复状态需要判断有效性拦截策略，命中拦截不能取消
            if (ForecastStatusEnum.of(status).equals(ForecastStatusEnum.WAITING_FOR_REPLY)) {
                waitReplyList.add(forecastOrderSDO);
            }
        }

        //待回复状态的保存需要效验有效性策略 20220405需求 待回复状态取消(add by myw) 只有业务员角色才效验待回复状态的有效性检查
        //判断待回复状态的订单是否可以取消
        //根据查询结果 判断是时间段还是截止时间 是拦截还是提示
        //如果是拦截的话不允许取消  提示的话可以取消
        checkValidity(waitReplyList);

        // 批量改变状态
        Integer count = forecastOrderWriteRepository.batchModify(ids);

        for (String id : ids) {
            //add by 皓晖 at 20211217 for 发送取消预报订单消息 begin
            this.cancelSendMsg(id);
            //add by 皓晖 at 20211217 for 发送取消预报订单消息 end
        }
        for (ForecastOrderSDO forecastOrderSDO : forecastOrderSDOList) {
            forecastOrderSDO.setStatus(ForecastStatusEnum.CANCELLED.getNumValue());
            LogUtils.printOperateLog(forecastOrderSDO, ForecastOrderLogEnum.CANCEL.getForecastOrderLogValue(), "取消预报订单", loginUser);
        }

        cancelForecastOrderReponse.setCount(count);
        return Result.success(cancelForecastOrderReponse);
    }

    private void checkValidity(List<ForecastOrderSDO> waitReplyList) {
        EmployeeGetCurrentLoginResponse currentLoginResponse = bcOrderService.employeeGetCurrentLogin();
        if (CollectionUtils.isNotEmpty(waitReplyList)&&currentLoginResponse.getOnlySales()) {

            for (ForecastOrderSDO forecastOrderSDO : waitReplyList) {
                MoreConditionQueryRequest moreConditionQueryRequest = new MoreConditionQueryRequest();
                moreConditionQueryRequest.setStrategyType(StrategyTypeEnum.VALIDITY.getCode());
                moreConditionQueryRequest.setOrganizationCode(forecastOrderSDO.getOrganizationCode());//forecastOrderSDO.getOrganizationCode()
                moreConditionQueryRequest.setChannelCode(forecastOrderSDO.getChannelCode());//forecastOrderSDO.getChannelCode()
                moreConditionQueryRequest.setWareHouseCode(forecastOrderSDO.getWareHouseCode());
                log.info("ForecastOrderEntity|save|"+forecastOrderSDO.getOrderBizId()+"|查询有效期校验|request|", JSONObject.toJSONString(moreConditionQueryRequest));
                Result<MoreConditionQueryResponse> moreConditionQueryResponseResult = strategyQueryService.moreConditionQuery(moreConditionQueryRequest);
                log.info("ForecastOrderEntity|save|"+forecastOrderSDO.getOrderBizId()+"|查询有效期校验|result|", JSONObject.toJSONString(moreConditionQueryResponseResult));
                MoreConditionQueryResponse moreConditionQueryResponse = moreConditionQueryResponseResult.getResult();

                if (Objects.nonNull(moreConditionQueryResponse)) {
                    StrategySDO strategySDO = moreConditionQueryResponse.getStrategySDO();
                    List<DimensionSDO> dimensionSDOList = strategySDO.getDimensionSDOList();
                    DimensionSDO dimensionSDO = dimensionSDOList.get(0);
                    //获取规则
                    String value = dimensionSDO.getRuleName();
                    if (StringUtils.equals(RuleTypeEnum.TIME_POINT.getCode(), value)) {
                        //获取规则值
                        String ruleValue = dimensionSDO.getRuleValue();
                        //判断截止时间是否满足 当前时间大于截止时间 不满足
                        boolean compare = CalendarCompareUtil.compareDateTimes(null, ruleValue);
                        if (compare) {
                            Boolean executeAction = dimensionSDO.getExecuteAction();
                            if (executeAction) {
                                throw new FunctionException("OTS-04-001-00-15-048","该时间范围内不允许修改，请联系订单员修改");
                                // return "该时间范围内不允许修改，请联系订单员修改";
                            }
                        }
                    }
                    if (StringUtils.equals(RuleTypeEnum.TIME_FRAME.getCode(), value)) {
                        String ruleValue = dimensionSDO.getRuleValue();
                        String substring = ruleValue.substring(ruleValue.indexOf("[") + 1, ruleValue.indexOf("]") ).replace("\"", "");
                        String[] split = substring.split(",");

                        String ruleValueSplit = split[0];
                        String ruleValueSplit1 = split[1];
                        boolean compareDateTimes = CalendarCompareUtil.compareDateTimes(ruleValueSplit, ruleValueSplit1);
                        //如果为true满足可以取消
                        if (!compareDateTimes) {
                            Boolean executeAction = dimensionSDO.getExecuteAction();
                            if (executeAction) {
                                throw new FunctionException("OTS-04-001-00-15-048","该时间范围内不允许修改，请联系订单员修改");
                                // return "该时间范围内不允许修改，请联系订单员修改";
                            }
                        }
                    }
                }
            }

        }
    }

    /**
     * 取消预报订单-发送消息
     */
    private void cancelSendMsg(String id) {
        ForecastOrderLineSDO queryParam = new ForecastOrderLineSDO();
        queryParam.setMainOrderId(id);
        List<ForecastOrderLineSDO> orderLineSDOS = this.forecastOrderLineQueryRepository.queyrLineDetailList(queryParam);
        if (orderLineSDOS != null) {
            for (ForecastOrderLineSDO paramLineSDO : orderLineSDOS) {
                this.sendMessage("ForecastCancled", paramLineSDO);
                paramLineSDO.setStatus(ForecastStatusEnum.CANCELLED.getNumValue());
                forecastOrderLineWriteRepository.update(paramLineSDO);
            }
        }
    }

    @Override
    @FacadeInvoker
    public Result<Boolean> submitForecast(SubmitForecastRequest submitForecastRequest) {
        log.info("预报订单提交入参 = {}", JSONObject.toJSONString(submitForecastRequest));
        if (CollectionUtils.isEmpty(submitForecastRequest.getForecastOrderSDOList())) {
            throw new FacadeException("OTS-04-001-00-15-013");
        }

        List<ForecastOrderSDO> forecastOrderSDOList = submitForecastRequest.getForecastOrderSDOList();
        for (ForecastOrderSDO forecastOrderSDO : forecastOrderSDOList) {
            //获取主单Id
            String orderId = forecastOrderSDO.getId();
            if (StringUtils.isNotEmpty(orderId)) {
                //调用load方法查询 预报订单数据
                ForecastOrderEntity forecastOrderEntity = ForecastOrderFactory.loadById(orderId);
                return forecastOrderEntity.submit(JSONObject.parseObject(JSONObject.toJSONString(submitForecastRequest.getApiContext()), ApiContext.class));
            }
        }
        log.error("ForecastOrderWriteServiceImpl#submitForecast_fail");
        return Result.success(false);
    }

    /**
     * 将orderline加载放到读取消息过程中，发送消息，只发送orderline id
     */
    @Override
    @FacadeInvoker
    public Result<Boolean> batchAnalysisOrders(BatchAnalysisOrdersRequest batchAnalysisOrdersRequest) {
        if (Objects.isNull(batchAnalysisOrdersRequest)) {
            //data 赋值 false
            return Result.fail(false, "SYS_ERR_INVALID_PARAM", "系统错误，参数异常！");
        }

        if (CollectionUtils.isEmpty(batchAnalysisOrdersRequest.getIds())) {
            return Result.success(true, "分析内容为空!");
        }
        log.info("预报批量分析入参 = {}", JSONObject.toJSONString(batchAnalysisOrdersRequest));

        try {
            String batchNo = String.valueOf(System.nanoTime());
            // 按照批次号和user查询订单列表
            //20220312，解决分析中还可以再次分析问题，将设置分析中操作放到发送消息前，修改为同步
            List<ForecastOrderLineEntity> forecastOrderLineEntities;
            forecastOrderLineEntities = ForecastOrderLineFactory.loadNotAnalyzingOrderLineListByIds(batchAnalysisOrdersRequest);
            if (Objects.isNull(forecastOrderLineEntities)){
                log.error("子单正在分析中");
                return Result.fail(false, "SYS_ERR_ORDERLINE_ANALYZING", "子单正在分析中，请稍后重试！");
            }
            saveBatchAaveavenalyzeStatusToAnalyzing(forecastOrderLineEntities, batchNo);

            boolean result = sendAnalyzeMessage(batchAnalysisOrdersRequest, batchNo);

            return Result.success(result, batchNo);
        } catch (Throwable e) {
            log.error("批量分析异常", e);
            throw new FunctionException("OTS-04-001-00-15-010");
        }
    }

    /**
     * 发送分析消息
     * 1、消息内容为待分析的子单id
     *
     * @param batchAnalysisOrdersRequest
     * @param batchNo
     * @return
     */
    private boolean sendAnalyzeMessage(BatchAnalysisOrdersRequest batchAnalysisOrdersRequest, String batchNo) {
        //分析数据设置值
        HashMap<String, Object> message = new HashMap<>();
        message.put(ANALYZE_TYPE, batchAnalysisOrdersRequest.getType());
        message.put(ANALYZE_BATCH_NO, batchNo);
        message.put(ANALYZE_USER_NO, batchAnalysisOrdersRequest.getModifierId());
        message.put(ANALYZE_ORDER_LINE_IDS, batchAnalysisOrdersRequest.getIds());
        message.put(ANALYZE_API_CONTEXT, batchAnalysisOrdersRequest.getApiContext());

        Map<String, String> map = new HashMap<>();
        map.put("_CZ_KEY", BcOrderConstants.TENANT_ID());
        return messageService.sendMessage(ANALYZE_MESSAGE_CODE, ANALYZE_MESSAGE_TOPIC, ANALYZE_MESSAGE_TAG,
                batchNo, JSON.toJSONString(message), map);
    }

    /**
     * 设置分析状态为分析中，子单deal_status及deal_line status都设置为1并保存数据库
     *
     * @param forecastOrderLineEntities 需要设置的子单集合
     * @param batchNo                   批次号
     * @return 成功：true
     * 失败：false
     */
    @EpochTransactional(appCode = "cr_forecast_sales", dataSourceCode = "cr_ots")
    private boolean saveBatchAaveavenalyzeStatusToAnalyzing(List<ForecastOrderLineEntity> forecastOrderLineEntities, String batchNo) {
        LoginUser loginUser = epochLoginUserService.getLoginUser();
        if (CollectionUtils.isEmpty(forecastOrderLineEntities)) {
            return false;
        }
        ForecastOrderLineEntity.setOrderLineStatusToAnalyzing(forecastOrderLineEntities);

        //将数据的信息插入分析队列的表中
        List<DealLineSDO> orderLineListToDeal = Nullable.stream(forecastOrderLineEntities).map(it -> {
            ForecastOrderLineSDO forecastOrderLineSDO = it.getForecastOrderLineSDO();
            DealLineSDO dealLineSDO = new DealLineSDO();
            dealLineSDO.setForecastOrderLineId(forecastOrderLineSDO.getId().toString());
            dealLineSDO.setDealStatus(ForecastDealStatusSEO.ANALYSIS_ING.getStatus());
            dealLineSDO.setDealType(ForecastDealTypeSEO.BATCH_ANALYSIS.getDealTypeCode().toString());
            dealLineSDO.setModifierName(forecastOrderLineSDO.getModifierName());
            dealLineSDO.setModifierId(forecastOrderLineSDO.getModifierId());
            dealLineSDO.setDealTime(new Date());
            dealLineSDO.setStatus(1);
            dealLineSDO.setBatchNumber(batchNo);

            //添加日志
            //LogUtils.printOperateLog(forecastOrderLineSDO.getMainOrderId(), ForecastOrderLogEnum.BATCH_ANALYSIS.getForecastOrderLogValue(), "分析订单",loginUser);
            return dealLineSDO;
        }).collect(Collectors.toList());

        //创建分析队列的表中数据
        dealLineWriteRepository.batchCreate(orderLineListToDeal);
        return true;
    }

    /**
     * 打印操作日志
     *
     * @param forecastOrderLineSDO
     * @param modifierName
     * @param activeValue          激活值
     */
    @Deprecated
    private void printOperateLog(ForecastOrderLineSDO forecastOrderLineSDO, String modifierName, String activeValue, Integer type) {
        OpLogModel.OpLogModelBuilder<String> builder = OpLogModel.builder();
        OpLogModel<String> opLogModel = builder.build();
        opLogModel.setModuleName(ModuleEnum.FORECAST_SALES.getModuleName());
        opLogModel.setModuleId(String.valueOf(ModuleEnum.FORECAST_SALES.getModuleId()));
        //ForecastOrderLogEnum 类型使用的枚举值，解析过程在纪元中
        opLogModel.setOperateType(type);
        opLogModel.setObjectId(forecastOrderLineSDO.getMainOrderId());
        opLogModel.setObjectName("id");
        Map<String, String> map = new HashMap<>();
        map.put("name", modifierName);
        map.put("active", activeValue);
        String logInfo = JSONObject.toJSONString(map);
        opLogModel.setFeatures(logInfo);
        opLogModel.setOperatorId(modifierName);
        opLogModel.setOperatorType(OperatorType.USER.getOperatorType());
        log.asyncMonitorObjectChangeV2(opLogModel);
    }

    /**
     * 预报订单分析消息处理入口
     *
     * @param analysisDealMsgHandleRequest
     * @return
     */
    @Override
    @FacadeInvoker
    public Result<Void> analysisDealMsgHandle(AnalysisDealMsgHandleRequest analysisDealMsgHandleRequest) {


        if (Objects.isNull(analysisDealMsgHandleRequest)) {
            return Result.fail("SYS_ERR_ANY_INVALID_PARAM", "系统异常，消息内容为空");
        }
        String message = analysisDealMsgHandleRequest.getMessage();

        if (StringUtils.isBlank(message)) {
            return Result.fail("SYS_ERR_ANY_INVALID_MSG", "系统异常，项目内容为空");
        }
        BatchAnalysisOrdersRequest pageQueryForecastRequest = new BatchAnalysisOrdersRequest();

        String type = "";
        List<String> ids = new ArrayList<>();
        ApiContext apiContext = null;
        try {
            JSONObject jsonObject = JSONObject.parseObject(message);
            // 消息转换
            // 通过消息获取
            String batchNumber = jsonObject.getString(ANALYZE_BATCH_NO);
            type = jsonObject.getString(ANALYZE_TYPE);
            ids = jsonObject.getJSONArray(ANALYZE_ORDER_LINE_IDS).toJavaList(String.class);
            apiContext = jsonObject.getObject(ANALYZE_API_CONTEXT, ApiContext.class);
            pageQueryForecastRequest.setIds(ids);

            log.info("analysisDeal Step -1 start analysisDeal#new logic, batch no:{}", batchNumber);

            // 按照批次号和user查询订单列表
            List<ForecastOrderLineEntity> forecastOrderLineEntities;
            forecastOrderLineEntities = ForecastOrderLineFactory.loadOrderLinesByIds(pageQueryForecastRequest);
            List<ForecastOrderLineSDO> batchAnalysisOrdersRequest;
            if (CollectionUtils.isNotEmpty(forecastOrderLineEntities)) {
                batchAnalysisOrdersRequest = Nullable.stream(forecastOrderLineEntities).map(it -> it.getForecastOrderLineSDO()).collect(Collectors.toList());

                //设置状态
                //20220312，解决分析中还可以再次分析问题，将设置分析中操作放到发送消息前，修改为同步
                //forecastOrderLineAbility.setBatchAnalyzeStatusToAnalyzing(forecastOrderLineEntities, batchNumber);
                //2022.10.28 新增 仅加入队列无活动类型 onlyJoinWithoutActivity
                scanQueue.analyzeOrderLineList(batchNumber, batchAnalysisOrdersRequest,
                        ONLY_JOIN_WITHOUT_ACTIVITY.equals(type));
            }
        } catch (Exception e) {
            log.error("Parse message failed:" + e.getMessage(), e);
        }

        // 根据type决定是否走确认逻辑
        if (AUTO_CREATE_SALE_ORDER_FLAG.equalsIgnoreCase(type)) {
            try {
                BatchSaveOrderConfirmRequest batchSaveOrderConfirmRequest = new BatchSaveOrderConfirmRequest();
                batchSaveOrderConfirmRequest.setIds(ids);
                batchSaveOrderConfirmRequest.setApiContext(apiContext);
                crForecastSalesService.batchSaveOrderConfirm(batchSaveOrderConfirmRequest);
            } catch (Exception e) {
                log.error("analysisDeal submit failed:" + e.getMessage(), e);
            }
        }

        log.info("analysisDeal Step 999 end, analysisDeal#new logic");
        return Result.success(null);
    }

    /**
     * 批量修改
     *
     * @param updateForecastQtyRequest
     * @return
     */
    @Override
    @FacadeInvoker
    @EpochTransactional(appCode = "cr_forecast_sales", dataSourceCode = "cr_ots")
    public Result<Boolean> batchUpdateReplyQuantity(UpdateForecastQtyRequest updateForecastQtyRequest) {
        log.info("预报修改回复数量入参 = {}", JSONObject.toJSONString(updateForecastQtyRequest));
        if (CollectionUtils.isEmpty(updateForecastQtyRequest.getForecastOrderLineSDOList())) {
            return null;
        } else {
            RefuseForecastRequest refuseForecastRequest = new RefuseForecastRequest();
            List<RefuseForecastDetailRequest> refuseForecastDetailRequests = new ArrayList<>();
            updateForecastQtyRequest.getForecastOrderLineSDOList().stream().forEach(i -> {
                //走拒绝逻辑
                if (StringUtils.isNotEmpty(i.getRefuseReasonCode())) {
                    RefuseForecastDetailRequest refuseForecastDetailRequest = new RefuseForecastDetailRequest();
                    refuseForecastDetailRequest.setId(String.valueOf(i.getId()));
                    refuseForecastDetailRequest.setRefuseReasonCode(i.getRefuseReasonCode());
                    refuseForecastDetailRequests.add(refuseForecastDetailRequest);
                }
            });
            refuseForecastRequest.setRefuseForecastDetailRequests(refuseForecastDetailRequests);
            if (Objects.nonNull(refuseForecastRequest) && CollectionUtils.isNotEmpty(refuseForecastDetailRequests)) {
                batchRefuseForecast(refuseForecastRequest);
            }

        }
        List<ForecastOrderLineSDO> ForecastOrderLineSDONew = updateForecastQtyRequest.getForecastOrderLineSDOList().stream().filter(i -> StringUtils.isEmpty(i.getRefuseReasonCode())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(ForecastOrderLineSDONew)) {
            return Result.success(true);
        }
        boolean b = forecastOrderLineAbility.updateReplyQuantity(ForecastOrderLineSDONew);
        List<String> collect = Nullable.stream(ForecastOrderLineSDONew).map(it -> {
            return it.getId().toString();
        }).collect(Collectors.toList());
        ForecastOrderActivityRequest forecastOrderActivityRequest = ForecastOrderActivityRequest.builder().ids(collect).build();
        try {
            applicationContext.getBean(ForecastOrderWriteServiceImpl.class).batchActivityCheckForecast(forecastOrderActivityRequest);
        } catch (Exception e) {
            log.error("ForecastOrderWriteServiceImpl#batchUpdateReplyQuantity_fail");
            log.error("预报订单活动检查出错", e);
        }

        if (!b) {
            log.error("ForecastOrderWriteServiceImpl#batchUpdateReplyQuantity_fail");
        }
        return Result.success(b);
    }

    private Result<List<BatchCreateOrderResponse>> confirmForecastOrderByOne(ConfirmForecastRequest confirmForecastRequest, ForecastOrderEntity forecastOrderEntity, Map<String, String> inventoryMap) {

        //1、更新子单状态确认中 ，加入队列表
        forecastOrderEntity.confirmUpdateDealForecast(JSONObject.parseObject(JSONObject.toJSONString(confirmForecastRequest.getApiContext()), ApiContext.class));

        //2、确认校验库存和活动
        ConfirmForecastResponse confirmForecastResponse = forecastOrderEntity.confirmCheckForecastNew(confirmForecastRequest,inventoryMap);
        ForecastOrderSDO forecastOrder = forecastOrderEntity.getForecastOrderSDO();
        Map<Long, ForecastOrderLineSDO> lineSDOMap = forecastOrder.getForecastOrderLineSDOList().stream().collect(Collectors.toMap(ForecastOrderLineSDO::getId, f -> f));
        log.info("ForecastOrderWriteServiceImpl#confirmForecastOrderByOne checkInventory " + forecastOrder.getOrderBizId() + JSON.toJSONString(confirmForecastResponse));
        Map<String, String> success = confirmForecastResponse.getSuccessOrderLineMap();
        Map<String, String> fail = confirmForecastResponse.getFailOrderLineMap();
        if (MapUtils.isNotEmpty(confirmForecastResponse.getFailOrderLineMap())) {
            confirmForecastResponse.getFailOrderLineMap().forEach((k, v) -> {
                forecastOrderEntity.backForecastUpdate(lineSDOMap.get(Long.valueOf(k)), fail.get(k));
            });
            forecastOrder.getForecastOrderLineSDOList().forEach(forecast -> {
                String msg = "";
                if (!fail.containsKey(forecast.getId().toString())) {
                    if (MapUtils.isNotEmpty(success)) {
                        msg = success.get(forecast.getId().toString());
                    }
                    forecastOrderEntity.backForecastUpdate(forecast, msg);
                }
            });
            log.error("ForecastOrderWriteServiceImpl#confirmForecastOrderByOne_fail " + forecastOrder.getOrderBizId());
            throw new FunctionException("OTS-04-001-00-15-027", forecastOrder.getOrderBizId() + "|" + confirmForecastResponse.getMessage());
        }
        log.error("666-拆单前--forecastOrderEntity:{}", forecastOrderEntity);
        //校验活动等信息
        List<ForecastOrderEntity> forecastOrderEntities = ForecastOrderFactory.batchCreateForecastOrder(forecastOrderEntity);
        log.error("666-拆单后--forecastOrderEntities:{}", forecastOrderEntities);

        //构造orderSDO对象
        List<OrderSDO> orderSDOS = ForecastOrderFactory.batchCreateOrder(forecastOrderEntities, confirmForecastRequest);
        log.error("666-销售单生成--forecastOrderEntities:{}", forecastOrderEntities);

        SaveSaleOrderRequest saveSaleOrderRequest = new SaveSaleOrderRequest();
        saveSaleOrderRequest.setOrderSDOS(orderSDOS);
        //保存订单
        Result<List<BatchCreateOrderResponse>> response = orderWriteService.saveSaleOrder(saveSaleOrderRequest);
        log.info("BatchCreateOrderResponse 销售订单创建:" + JSON.toJSONString(response));
        if (response == null || CollectionUtils.isEmpty(response.getResult())) {
            throw new FunctionException("OTS-04-001-00-15-037");
        }
        List<BatchCreateOrderRequest> confirmForecastStatuses = new ArrayList<>();
        response.getResult().forEach(batchCreateOrderResponse -> {
            BatchCreateOrderRequest batchCreateOrderRequest = new BatchCreateOrderRequest();
            BeanUtils.copyProperties(batchCreateOrderResponse, batchCreateOrderRequest);
            confirmForecastStatuses.add(batchCreateOrderRequest);
        });
        confirmForecastRequest.setConfirmForecastStatuses(confirmForecastStatuses);
        if (MapUtils.isNotEmpty(success)) {
            success.forEach((k, v) -> {
                forecastOrderEntity.backForecastUpdate(lineSDOMap.get(Long.valueOf(k)), success.get(k));
            });
        }

        // 更新预报单状态
        this.batchConfirmUpdateForecast(confirmForecastRequest);

        return response;
    }

    private Result<List<BatchCreateOrderResponse>> syncConfirmForecastOrderByOne(ConfirmForecastRequest confirmForecastRequest, ForecastOrderEntity forecastOrderEntity, Map<String, String> inventoryMap, Map<String, String> fulfillmentMap) {

        //1、更新子单状态确认中 ，加入队列表
        forecastOrderEntity.confirmUpdateDealForecast(JSONObject.parseObject(JSONObject.toJSONString(confirmForecastRequest.getApiContext()), ApiContext.class));

        //2、确认校验库存和活动
        ConfirmForecastResponse confirmForecastResponse = forecastOrderEntity.syncConfirmCheckForecastNew(confirmForecastRequest,inventoryMap);
        ForecastOrderSDO forecastOrder = forecastOrderEntity.getForecastOrderSDO();
        Map<Long, ForecastOrderLineSDO> lineSDOMap = forecastOrder.getForecastOrderLineSDOList().stream().collect(Collectors.toMap(ForecastOrderLineSDO::getId, f -> f));
        log.info("ForecastOrderWriteServiceImpl#syncConfirmForecastOrderByOne checkInventory " + forecastOrder.getOrderBizId() + JSON.toJSONString(confirmForecastResponse));
        Map<String, String> success = confirmForecastResponse.getSuccessOrderLineMap();
        Map<String, String> fail = confirmForecastResponse.getFailOrderLineMap();
        if (MapUtils.isNotEmpty(confirmForecastResponse.getFailOrderLineMap())) {
            confirmForecastResponse.getFailOrderLineMap().forEach((k, v) -> {
                forecastOrderEntity.backForecastUpdate(lineSDOMap.get(Long.valueOf(k)), fail.get(k));
            });
            forecastOrder.getForecastOrderLineSDOList().forEach(forecast -> {
                String msg = "";
                if (!fail.containsKey(forecast.getId().toString())) {
                    if (MapUtils.isNotEmpty(success)) {
                        msg = success.get(forecast.getId().toString());
                    }
                    forecastOrderEntity.backForecastUpdate(forecast, msg);
                }
            });
            log.error("ForecastOrderWriteServiceImpl#syncConfirmForecastOrderByOne_fail " + forecastOrder.getOrderBizId());
            throw new FunctionException("OTS-04-001-00-15-027", forecastOrder.getOrderBizId() + "|" + confirmForecastResponse.getMessage());
        }
        log.error("666-拆单前--forecastOrderEntity:{}", forecastOrderEntity);
        //校验活动等信息
        List<ForecastOrderEntity> forecastOrderEntities = ForecastOrderFactory.batchSyncCreateForecastOrder(forecastOrderEntity,fulfillmentMap);
        log.error("666-拆单后--forecastOrderEntities:{}", forecastOrderEntities);

        //构造orderSDO对象
        List<OrderSDO> orderSDOS = ForecastOrderFactory.batchCreateOrder(forecastOrderEntities, confirmForecastRequest);
        log.error("666-销售单生成--forecastOrderEntities:{}", forecastOrderEntities);

        SaveSaleOrderRequest saveSaleOrderRequest = new SaveSaleOrderRequest();
        saveSaleOrderRequest.setOrderSDOS(orderSDOS);
        //保存订单
        Result<List<BatchCreateOrderResponse>> response = orderWriteService.saveSaleOrder(saveSaleOrderRequest);
        log.info("BatchCreateOrderResponse 销售订单创建:" + JSON.toJSONString(response));
        if (response == null || CollectionUtils.isEmpty(response.getResult())) {
            throw new FunctionException("OTS-04-001-00-15-037");
        }
        List<BatchCreateOrderRequest> confirmForecastStatuses = new ArrayList<>();
        response.getResult().forEach(batchCreateOrderResponse -> {
            BatchCreateOrderRequest batchCreateOrderRequest = new BatchCreateOrderRequest();
            BeanUtils.copyProperties(batchCreateOrderResponse, batchCreateOrderRequest);
            confirmForecastStatuses.add(batchCreateOrderRequest);
        });
        confirmForecastRequest.setConfirmForecastStatuses(confirmForecastStatuses);
        if (MapUtils.isNotEmpty(success)) {
            success.forEach((k, v) -> {
                forecastOrderEntity.backForecastUpdate(lineSDOMap.get(Long.valueOf(k)), success.get(k));
            });
        }

        // 更新预报单状态
        this.batchConfirmUpdateForecast(confirmForecastRequest);

        return response;
    }

    @Override
    @FacadeInvoker
    public Result<Boolean> confirmUpdateDealForecastNew(ConfirmForecastRequest confirmForecastRequest) {
        Result<Boolean> result = batchConfirmUpdateDealForecastV2(confirmForecastRequest);
        //返回对象null值判断
        if (Objects.isNull(result) || !result.getResult() || !result.isSuccess()) {//接口上一步在fail中没有传boolean值，造成fail时npe，应该用isSuccess判断上一步结果
            log.error("ForecastOrderWriteServiceImpl#confirmUpdateDealForecastNew_fail");
        }
        return result;
    }

    private Result<Boolean> batchConfirmUpdateDealForecastV2(ConfirmForecastRequest confirmForecastRequest) {
        if (Objects.isNull(confirmForecastRequest)||CollectionUtils.isEmpty(confirmForecastRequest.getIds())){
            return Result.fail(false, "", "未勾选任何订单明细行，不允许批量确认生成销售订单，请勾选明细行！");
        }
        LoginUser loginUser = epochLoginUserService.getLoginUser();
        log.info("ForecastOrderWriteServiceImpl|batchConfirmUpdateDealForecastV2|批量确认|参数01 = {}", JSONObject.toJSONString(confirmForecastRequest));
        //根据主订单进行分组
        List<ForecastOrderEntity> forecastOrderEntities = ForecastOrderFactory.confirmForecast(confirmForecastRequest);
        //批量同步sap销售订单集合
        List<BatchCreateOrderResponse> integratedOrderList=new ArrayList<>();
        //创建任务
        String taskId = startTask(confirmForecastRequest, forecastOrderEntities, MessageTaskTypeEnum.BATCH_CONFIRM);
        //过滤预计回复数量为0，将确认状态改为确认中，避免页面没有及时刷新
        List<Long> shouldConfirmIdsAll=new ArrayList<>();
        for (ForecastOrderEntity forecastOrderEntity : forecastOrderEntities) {
            List<ForecastOrderLineSDO> forecastOrderLineSDOList = forecastOrderEntity.getForecastOrderSDO().getForecastOrderLineSDOList();
            List<ForecastOrderLineSDO> dissatisfyList = forecastOrderLineSDOList.stream().filter(o -> Objects.isNull(o.getPredictReplyAmount())
                    || o.getPredictReplyAmount() == 0|| !CAN_CONFIRM_FORECAST_STATUS.contains(o.getStatus())).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(dissatisfyList)){
                shouldConfirmIdsAll.addAll(forecastOrderLineSDOList.stream().map(ForecastOrderLineSDO::getId).collect(Collectors.toList()));
            }
        }
        com.epoch.app.crforecastsales.model.dto.ApiContext apiContext = confirmForecastRequest.getApiContext();
        if (CollectionUtils.isNotEmpty(shouldConfirmIdsAll)){
            BatchUpdateForConfirmRequest batchUpdateForConfirmRequest = new BatchUpdateForConfirmRequest();
            batchUpdateForConfirmRequest.setDealStatus(ForecastDealStatusSEO.CONFIRM_ING.getStatus());
            batchUpdateForConfirmRequest.setModifierId(apiContext.getEmployeeId());
            batchUpdateForConfirmRequest.setModifierName(apiContext.getEmployeeName());
            batchUpdateForConfirmRequest.setOrderLineIds(shouldConfirmIdsAll);
            forecastOrderLineWriteRepository.batchUpdateForConfirming(batchUpdateForConfirmRequest);
        }

        boolean res = true;
        StringBuilder orderIds = new StringBuilder();
        ErrorMessage errorMessage = new ErrorMessage();
        if (CollectionUtils.isNotEmpty(forecastOrderEntities)) {
            Map<String, String> inventoryMap = queryInventory(forecastOrderEntities);

            for (ForecastOrderEntity forecastOrderEntity : forecastOrderEntities) {
                ForecastOrderSDO forecastOrderSDO = forecastOrderEntity.getForecastOrderSDO();
                List<Long> forecastLineIds = forecastOrderSDO.getForecastOrderLineSDOList().stream().map(ForecastOrderLineSDO::getId).collect(Collectors.toList());
                try (RedisLock lock = new RedisLock("REDIS_CACHE", "batch:" + forecastOrderEntity.getForecastOrderSDO().getId(), 0, 30 * 1000)) {
                    if (!lock.lock()) {
                        errorMessage = ErrorMessage.code("OTS-04-001-00-15-038", orderIds + "该单据正在参与其它操作，请稍后重试");
                        res = false;
                        continue;
                    }
                    //已完成的预报子单不允许再确认
                    List<ForecastOrderLineSDO> completeLineList = forecastOrderSDO.getForecastOrderLineSDOList().stream().filter(o -> !CAN_CONFIRM_FORECAST_STATUS.contains(o.getStatus())).collect(Collectors.toList());
                    if (CollectionUtils.isNotEmpty(completeLineList)){
                        errorMessage = ErrorMessage.code("OTS-04-001-00-15-055", orderIds + "有部分单据状态已变更，不可确认");
                        res = false;
                        continue;
                    }

                    Result<List<BatchCreateOrderResponse>> confirmResult = confirmForecastOrderByOne(confirmForecastRequest, forecastOrderEntity, inventoryMap);
                    if (CollectionUtils.isNotEmpty(confirmResult.getResult())){
                        integratedOrderList.addAll(confirmResult.getResult());
                    }
                } catch (FunctionException e) {
                    FailOrderRequest failOrderRequest = new FailOrderRequest();
                    failOrderRequest.setFailOrderIds(forecastLineIds);
                    failOrderRequest.setApiContext(apiContext);
                    failOrderRequest.setSequenceNo(confirmForecastRequest.getSequenceNo());
                    failOrderService.sendFailMsg(failOrderRequest);
                    orderIds.append(forecastOrderSDO.getOrderBizId()).append("|");
                    errorMessage = e.getError();
                    res = false;
                    continue;
                } catch (Throwable e) {
                    log.error("ForecastOrderWriteServiceImpl#batchConfirmUpdateDealForecastV2 error", e);
                    continue;
                }

                // 获取预报单状态
                ForecastOrderSDO queryForecastOrderSDO = forecastOrderQueryRepository.load(forecastOrderEntity.getForecastOrderSDO().getId());
                // 添加日志
                LogUtils.printOperateLog(queryForecastOrderSDO, ForecastOrderLogEnum.BATCH_CONFIRM.getForecastOrderLogValue(), "确认预报订单", loginUser);

            }
            if (CollectionUtils.isNotEmpty(integratedOrderList)) {
                List<TradeMessageSDO> tradeMessageSDOS = integratedOrderList.stream()
                        .map(BatchCreateOrderResponse::getTradeMessageSDO)
                        .filter(Objects::nonNull).distinct().collect(Collectors.toList());

                updateTask(integratedOrderList, taskId);
                // sap发送订单创建消息
                if (CollectionUtils.isNotEmpty(tradeMessageSDOS)){
                    Map<String, String> map = new HashMap<>();
                    map.put("_CZ_KEY", BcOrderConstants.TENANT_ID());
                    String sequenceNo = confirmForecastRequest.getSequenceNo();
                    messageService.sendMessage("sale_order_message", "CR_SALEORDER_V2", "SaleBatchCreated", sequenceNo, sequenceNo,map);
                }
            }
            if (!res) {
                log.error("ForecastOrderWriteServiceImpl#batchConfirmUpdateDealForecastV2_fail");
                // add data content
                return Result.fail(false, errorMessage.getErrorCode(), errorMessage.getDisplayErrorMessage());
            }
        }
        return Result.success(Boolean.TRUE);
    }

    @Override
    @FacadeInvoker
    public Result<List<ConfirmForecastDTO>> batchConfirmForecastBiz(BatchConfirmForecastBiz batchConfirmForecastBiz) {
        ConfirmForecastRequest confirmForecastRequest = new ConfirmForecastRequest();
        confirmForecastRequest.setIds(batchConfirmForecastBiz.getIds());
        com.epoch.app.crforecastsales.model.dto.ApiContext apiContext = new com.epoch.app.crforecastsales.model.dto.ApiContext();
        apiContext.setEmployeeId(batchConfirmForecastBiz.getModifierId());
        apiContext.setEmployeeName(batchConfirmForecastBiz.getModifierName());
        confirmForecastRequest.setSequenceNo(batchConfirmForecastBiz.getSequenceNo());
        confirmForecastRequest.setApiContext(apiContext);
        confirmForecastRequest.setOperatorCode(batchConfirmForecastBiz.getModifierCode());
        confirmForecastRequest.setOperatorId(batchConfirmForecastBiz.getModifierId());
        confirmForecastRequest.setOperatorName(batchConfirmForecastBiz.getModifierName());
        return batchConfirmForecastBiz(confirmForecastRequest);
    }


    private Result<List<ConfirmForecastDTO>> batchConfirmForecastBiz(ConfirmForecastRequest request) {
        log.info("ForecastOrderWriteServiceImpl.batchConfirmForecastBiz request={}", JSON.toJSONString(request));
        if (Objects.isNull(request) || CollectionUtils.isEmpty(request.getIds())) {
            return Result.fail("OC-04-005-01-16-002", "确认预报单为空!");
        }

        List<ConfirmForecastDTO> confirmForecastDTOS = new ArrayList<>();
        //根据入参单号查询预报单数据，并根据主订单进行分组
        List<ForecastOrderEntity> forecastOrderEntities = ForecastOrderFactory.confirmForecast(request);
        //批量同步sap销售订单集合
        List<BatchCreateOrderResponse> integratedOrderList = new ArrayList<>();
        //创建任务
        String taskId = startTask(request, forecastOrderEntities, MessageTaskTypeEnum.BATCH_CONFIRM);
        //过滤预计回复数量为0，将确认状态改为确认中，避免页面没有及时刷新
        List<Long> shouldConfirmIdsAll = new ArrayList<>();
        Map<String, ForecastOrderSDO> forecastOrderSDOMap = new HashMap<>();
        for (ForecastOrderEntity forecastOrderEntity : forecastOrderEntities) {
            List<ForecastOrderLineSDO> forecastOrderLineSDOList = forecastOrderEntity.getForecastOrderSDO().getForecastOrderLineSDOList();
            List<ForecastOrderLineSDO> dissatisfyList = forecastOrderLineSDOList.stream()
                    .filter(o -> Objects.isNull(o.getPredictReplyAmount()) || o.getPredictReplyAmount() == 0 || !CAN_CONFIRM_FORECAST_STATUS.contains(o.getStatus()) || !CAN_CONFIRM_FORECAST_DEAL_STATUS.contains(o.getDealStatus()))
                    .collect(Collectors.toList());

            if (CollectionUtils.isEmpty(dissatisfyList)) {
                shouldConfirmIdsAll.addAll(forecastOrderLineSDOList.stream().map(ForecastOrderLineSDO::getId).collect(Collectors.toList()));
                forecastOrderSDOMap.put(forecastOrderEntity.getForecastOrderSDO().getOrderBizId(), forecastOrderEntity.getForecastOrderSDO());
            }else{
                dissatisfyList.stream().forEach(orderLine -> {
                    Integer predictReplayAmount = orderLine.getPredictReplyAmount() == null ? 0 : orderLine.getPredictReplyAmount();
                    if (!CAN_CONFIRM_FORECAST_STATUS.contains(orderLine.getStatus())){
                        ConfirmForecastDTO confirmForecastDTO = new ConfirmForecastDTO();
                        confirmForecastDTO.setForecastOrderBizNO(orderLine.getMainOrderBizId());
                        confirmForecastDTO.setLineNo(orderLine.getSerialNumber());
                        confirmForecastDTO.setSuccess(false);
                        confirmForecastDTO.setErrorCode("OC-01-001-01-16-053");
                        confirmForecastDTO.setMessage("当前操作与订单可执行操作不匹配");
                        confirmForecastDTOS.add(confirmForecastDTO);
                    } else if (predictReplayAmount == 0) {
                        ConfirmForecastDTO confirmForecastDTO = new ConfirmForecastDTO();
                        confirmForecastDTO.setForecastOrderBizNO(orderLine.getMainOrderBizId());
                        confirmForecastDTO.setLineNo(orderLine.getSerialNumber());
                        confirmForecastDTO.setSuccess(false);
                        confirmForecastDTO.setErrorCode("OC-04-005-01-16-002");
                        confirmForecastDTO.setMessage("预计回复数量须为正整数");
                        confirmForecastDTOS.add(confirmForecastDTO);
                    } else if (!CAN_CONFIRM_FORECAST_DEAL_STATUS.contains(orderLine.getDealStatus())) {
                        if(ForecastDealStatusSEO.ANALYSIS_ING.getStatus().equals(orderLine.getDealStatus())){
                            ConfirmForecastDTO confirmForecastDTO = new ConfirmForecastDTO();
                            confirmForecastDTO.setForecastOrderBizNO(orderLine.getMainOrderBizId());
                            confirmForecastDTO.setLineNo(orderLine.getSerialNumber());
                            confirmForecastDTO.setSuccess(false);
                            confirmForecastDTO.setErrorCode("OC-04-005-01-16-006");
                            confirmForecastDTO.setMessage("存在预报单确认状态为分析中，不能回复确认");
                            confirmForecastDTOS.add(confirmForecastDTO);
                        } else if(ForecastDealStatusSEO.ANALYSIS_FAILED.getStatus().equals(orderLine.getDealStatus())){
                            ConfirmForecastDTO confirmForecastDTO = new ConfirmForecastDTO();
                            confirmForecastDTO.setForecastOrderBizNO(orderLine.getMainOrderBizId());
                            confirmForecastDTO.setLineNo(orderLine.getSerialNumber());
                            confirmForecastDTO.setSuccess(false);
                            confirmForecastDTO.setErrorCode("OC-04-005-01-16-007");
                            confirmForecastDTO.setMessage("存在预报单确认状态为分析失败，不能回复确认");
                            confirmForecastDTOS.add(confirmForecastDTO);
                        } else if(ForecastDealStatusSEO.CONFIRM_ING.getStatus().equals(orderLine.getDealStatus())){
                            ConfirmForecastDTO confirmForecastDTO = new ConfirmForecastDTO();
                            confirmForecastDTO.setForecastOrderBizNO(orderLine.getMainOrderBizId());
                            confirmForecastDTO.setLineNo(orderLine.getSerialNumber());
                            confirmForecastDTO.setSuccess(false);
                            confirmForecastDTO.setErrorCode("OC-04-005-01-16-009");
                            confirmForecastDTO.setMessage("存在预报单确认状态为确认中，不能回复确认");
                            confirmForecastDTOS.add(confirmForecastDTO);
                        }
                    }
                });
            }

//            if (CollectionUtils.isEmpty(dissatisfyList)) {
//                shouldConfirmIdsAll.addAll(forecastOrderLineSDOList.stream().map(ForecastOrderLineSDO::getId).collect(Collectors.toList()));
//            }
        }

        //将预报订单状态推进到【确认中】
        com.epoch.app.crforecastsales.model.dto.ApiContext apiContext = request.getApiContext();
        if (CollectionUtils.isNotEmpty(shouldConfirmIdsAll)) {
            BatchUpdateForConfirmRequest batchUpdateForConfirmRequest = new BatchUpdateForConfirmRequest();
            batchUpdateForConfirmRequest.setDealStatus(ForecastDealStatusSEO.CONFIRM_ING.getStatus());
            batchUpdateForConfirmRequest.setModifierId(request.getOperatorId());
            batchUpdateForConfirmRequest.setModifierName(request.getOperatorName());
//            batchUpdateForConfirmRequest.set(request.getOperateCode());
            batchUpdateForConfirmRequest.setOrderLineIds(shouldConfirmIdsAll);
            forecastOrderLineWriteRepository.batchUpdateForConfirming(batchUpdateForConfirmRequest);
        }

        List<ForecastOrderEntity> forecastOrderEntityList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(forecastOrderEntities)) {
            forecastOrderEntityList = forecastOrderEntities.stream().filter(forecastOrderEntity -> {
                return forecastOrderSDOMap.containsKey(forecastOrderEntity.getForecastOrderSDO().getOrderBizId());
            }).collect(Collectors.toList());
        }
        log.info("forecastOrderEntityList结果:{}",JSON.toJSONString(forecastOrderEntityList));



        if (CollectionUtils.isNotEmpty(forecastOrderEntityList)) {
            Map<String, String> inventoryMap = queryInventory(forecastOrderEntityList);

            for (ForecastOrderEntity forecastOrderEntity : forecastOrderEntityList) {
                ForecastOrderSDO forecastOrderSDO = forecastOrderEntity.getForecastOrderSDO();
                ErrorMessage errorMessage;
                ConfirmForecastDTO confirmForecastDTO = new ConfirmForecastDTO();
                confirmForecastDTO.setForecastOrderBizNO(forecastOrderSDO.getOrderBizId());
                confirmForecastDTO.setSuccess(Boolean.TRUE);
                List<Long> forecastLineIds = forecastOrderSDO.getForecastOrderLineSDOList().stream().map(ForecastOrderLineSDO::getId).collect(Collectors.toList());
                try (RedisLock lock = new RedisLock("REDIS_CACHE", "batch:" + forecastOrderEntity.getForecastOrderSDO().getId(), 0, 30 * 1000)) {
                    if (!lock.lock()) {
                        errorMessage = ErrorMessage.code("OTS-04-001-00-15-038", "该单据正在参与其它操作，请稍后重试");
                        confirmForecastDTO.setSuccess(Boolean.FALSE);
                        confirmForecastDTO.setMessage(errorMessage.getDisplayErrorMessage());
                        confirmForecastDTO.setErrorCode(errorMessage.getErrorCode());
                        confirmForecastDTOS.add(confirmForecastDTO);
                        continue;
                    }
                    // 一盘货改造: 前面提示了，这里不做校验
                    //已完成的预报子单不允许再确认
//                    List<ForecastOrderLineSDO> completeLineList = forecastOrderSDO.getForecastOrderLineSDOList().stream()
//                            .filter(o -> !CAN_CONFIRM_FORECAST_STATUS.contains(o.getStatus()))
//                            .collect(Collectors.toList());
//                    if (CollectionUtils.isNotEmpty(completeLineList)) {
//                        errorMessage = ErrorMessage.code("OTS-04-001-00-15-055", "有部分单据状态已变更，不可确认");
//                        confirmForecastDTO.setSuccess(Boolean.FALSE);
//                        confirmForecastDTO.setMessage(errorMessage.getDisplayErrorMessage());
//                        confirmForecastDTO.setErrorCode(errorMessage.getErrorCode());
//                        confirmForecastDTOS.add(confirmForecastDTO);
//                        continue;
//                    }

                    // 创建销售订单
                    Result<List<BatchCreateOrderResponse>> confirmResult = confirmForecastOrderByOne(request, forecastOrderEntity, inventoryMap);
                    if (CollectionUtils.isNotEmpty(confirmResult.getResult())) {
                        integratedOrderList.addAll(confirmResult.getResult());
                        confirmForecastDTOS.add(confirmForecastDTO);
                    }
                } catch (FunctionException e) {
                    FailOrderRequest failOrderRequest = new FailOrderRequest();
                    failOrderRequest.setFailOrderIds(forecastLineIds);
                    failOrderRequest.setApiContext(apiContext);
                    failOrderRequest.setSequenceNo(request.getSequenceNo());
                    failOrderService.sendFailMsg(failOrderRequest);

                    confirmForecastDTO.setSuccess(Boolean.FALSE);
                    confirmForecastDTO.setMessage(e.getErrorMessage());
                    confirmForecastDTO.setErrorCode(e.getErrorCode());
                    confirmForecastDTOS.add(confirmForecastDTO);
                } catch (Exception e) {
                    log.error("ForecastOrderWriteServiceImpl#batchConfirmForecastBiz error", e);

                    confirmForecastDTO.setSuccess(Boolean.FALSE);
                    confirmForecastDTO.setMessage(e.getMessage());
                    confirmForecastDTO.setErrorCode("OC-04-005-01-16-001");
                    confirmForecastDTOS.add(confirmForecastDTO);
                }
            }

            if (CollectionUtils.isNotEmpty(integratedOrderList)) {
                List<TradeMessageSDO> tradeMessageSDOS = integratedOrderList.stream()
                        .map(BatchCreateOrderResponse::getTradeMessageSDO)
                        .filter(Objects::nonNull).distinct().collect(Collectors.toList());

                updateTask(integratedOrderList, taskId);

                Map<String, String> map = new HashMap<>();
                map.put("_CZ_KEY", BcOrderConstants.TENANT_ID());

                if (CollectionUtils.isNotEmpty(tradeMessageSDOS)) {
                    // 发送创建sap订单消息
                    String sequenceNo = request.getSequenceNo();
                    messageService.sendMessage("sale_order_message", "CR_SALEORDER_V2", "SaleBatchCreated", sequenceNo, sequenceNo, map);
                }

                // 发送订单创建成功消息
                List<String> salesOrderIds = integratedOrderList.stream()
                        .map(BatchCreateOrderResponse::getOrderId)
                        .filter(Objects::nonNull).distinct().collect(Collectors.toList());

                if (CollectionUtils.isNotEmpty(salesOrderIds)) {
                    List<OrderSDO> orderSDOS = new ArrayList<>();
                    for (String salesOrderId : salesOrderIds) {
                        log.info("ForecastOrderWriteServiceImpl#batchConfirmForecastBiz salesOrderId={}", salesOrderId);
                        QuerySingleRequest querySingleRequest = new QuerySingleRequest();
                        querySingleRequest.setMainOrderId(salesOrderId);
                        OrderSDO orderSDO = orderQueryService.querySingle(querySingleRequest);
                        if (Objects.isNull(orderSDO)) {
                            log.info("ForecastOrderWriteServiceImpl#batchConfirmForecastBiz querySingle is empty");
                            continue;
                        }
                        orderSDOS.add(orderSDO);
                    }

                    CommonAsyncMessageResponse message = new CommonAsyncMessageResponse();
                    message.setEventCode(InnerMessageEventEnum.SALES_ORDER_CREATED.getValue());
                    message.setEventName(InnerMessageEventEnum.SALES_ORDER_CREATED.getLabel());
                    message.setData(orderSDOS);
                    String messageString = JSON.toJSONString(message);
                    log.info("ForecastOrderWriteServiceImpl#batchConfirmForecastBiz sendMessage message={}", messageString);

                    // 发送MQ消息通知其他中心
                    messageService.sendMessage("sale_order_message", "CR_SALEORDER_V2", "SalesOrderEvent", UUID.randomUUID().toString(), messageString, map);
                }
            }

        }
        return Result.success(confirmForecastDTOS);
    }

    @Override
    @FacadeInvoker
    public Result<List<ConfirmForecastDTO>> syncBatchConfirmForecastBiz(SyncBatchConfirmForecastBiz batchConfirmForecastBiz){
        ConfirmForecastRequest confirmForecastRequest = new ConfirmForecastRequest();
        confirmForecastRequest.setIds(batchConfirmForecastBiz.getIds());
        com.epoch.app.crforecastsales.model.dto.ApiContext apiContext = new com.epoch.app.crforecastsales.model.dto.ApiContext();
        apiContext.setEmployeeId(batchConfirmForecastBiz.getModifierId());
        apiContext.setEmployeeName(batchConfirmForecastBiz.getModifierName());
        confirmForecastRequest.setSequenceNo(batchConfirmForecastBiz.getSequenceNo());
        confirmForecastRequest.setApiContext(apiContext);
        confirmForecastRequest.setOperatorCode(batchConfirmForecastBiz.getModifierCode());
        confirmForecastRequest.setOperatorId(batchConfirmForecastBiz.getModifierId());
        confirmForecastRequest.setOperatorName(batchConfirmForecastBiz.getModifierName());
        return syncConfirmForecastBiz(confirmForecastRequest,batchConfirmForecastBiz.getFulfillmentMap());
    }

    private Result<List<ConfirmForecastDTO>> syncConfirmForecastBiz(ConfirmForecastRequest request, Map<String, String> fulfillmentMap) {
        log.info("ForecastOrderWriteServiceImpl.syncConfirmForecastBiz request={}", JSON.toJSONString(request));
        if (Objects.isNull(request) || CollectionUtils.isEmpty(request.getIds())) {
            return Result.fail("OC-04-005-01-16-002", "确认预报单为空!");
        }

        List<ConfirmForecastDTO> confirmForecastDTOS = new ArrayList<>();
        //根据入参单号查询预报单数据，并根据主订单进行分组
        List<ForecastOrderEntity> forecastOrderEntities = ForecastOrderFactory.confirmForecast(request);
        //批量同步sap销售订单集合
        List<BatchCreateOrderResponse> integratedOrderList = new ArrayList<>();
        //创建任务
        String taskId = startTask(request, forecastOrderEntities, MessageTaskTypeEnum.BATCH_CONFIRM);
        //过滤预计回复数量为0，将确认状态改为确认中，避免页面没有及时刷新
        List<Long> shouldConfirmIdsAll = new ArrayList<>();
        Map<String, ForecastOrderSDO> forecastOrderSDOMap = new HashMap<>();
        for (ForecastOrderEntity forecastOrderEntity : forecastOrderEntities) {
            List<ForecastOrderLineSDO> forecastOrderLineSDOList = forecastOrderEntity.getForecastOrderSDO().getForecastOrderLineSDOList();
            List<ForecastOrderLineSDO> dissatisfyList = forecastOrderLineSDOList.stream()
                    .filter(o -> Objects.isNull(o.getPredictReplyAmount()) || o.getPredictReplyAmount() == 0 || !CAN_CONFIRM_FORECAST_STATUS.contains(o.getStatus()) || !CAN_CONFIRM_FORECAST_DEAL_STATUS.contains(o.getDealStatus()))
                    .collect(Collectors.toList());

            if (CollectionUtils.isEmpty(dissatisfyList)) {
                shouldConfirmIdsAll.addAll(forecastOrderLineSDOList.stream().map(ForecastOrderLineSDO::getId).collect(Collectors.toList()));
                forecastOrderSDOMap.put(forecastOrderEntity.getForecastOrderSDO().getOrderBizId(), forecastOrderEntity.getForecastOrderSDO());
            }else{
                dissatisfyList.stream().forEach(orderLine -> {
                    Integer predictReplayAmount = orderLine.getPredictReplyAmount() == null ? 0 : orderLine.getPredictReplyAmount();
                    if (!CAN_CONFIRM_FORECAST_STATUS.contains(orderLine.getStatus())){
                        ConfirmForecastDTO confirmForecastDTO = new ConfirmForecastDTO();
                        confirmForecastDTO.setForecastOrderBizNO(orderLine.getMainOrderBizId());
                        confirmForecastDTO.setLineNo(orderLine.getSerialNumber());
                        confirmForecastDTO.setSuccess(false);
                        confirmForecastDTO.setErrorCode("OC-01-001-01-16-053");
                        confirmForecastDTO.setMessage("当前操作与订单可执行操作不匹配");
                        confirmForecastDTOS.add(confirmForecastDTO);
                    } else if (predictReplayAmount == 0) {
                        ConfirmForecastDTO confirmForecastDTO = new ConfirmForecastDTO();
                        confirmForecastDTO.setForecastOrderBizNO(orderLine.getMainOrderBizId());
                        confirmForecastDTO.setLineNo(orderLine.getSerialNumber());
                        confirmForecastDTO.setSuccess(false);
                        confirmForecastDTO.setErrorCode("OC-04-005-01-16-002");
                        confirmForecastDTO.setMessage("预计回复数量须为正整数");
                        confirmForecastDTOS.add(confirmForecastDTO);
                    } else if (!CAN_CONFIRM_FORECAST_DEAL_STATUS.contains(orderLine.getDealStatus())) {
                        if(ForecastDealStatusSEO.ANALYSIS_ING.getStatus().equals(orderLine.getDealStatus())){
                            ConfirmForecastDTO confirmForecastDTO = new ConfirmForecastDTO();
                            confirmForecastDTO.setForecastOrderBizNO(orderLine.getMainOrderBizId());
                            confirmForecastDTO.setLineNo(orderLine.getSerialNumber());
                            confirmForecastDTO.setSuccess(false);
                            confirmForecastDTO.setErrorCode("OC-04-005-01-16-006");
                            confirmForecastDTO.setMessage("存在预报单确认状态为分析中，不能回复确认");
                            confirmForecastDTOS.add(confirmForecastDTO);
                        } else if(ForecastDealStatusSEO.ANALYSIS_FAILED.getStatus().equals(orderLine.getDealStatus())){
                            ConfirmForecastDTO confirmForecastDTO = new ConfirmForecastDTO();
                            confirmForecastDTO.setForecastOrderBizNO(orderLine.getMainOrderBizId());
                            confirmForecastDTO.setLineNo(orderLine.getSerialNumber());
                            confirmForecastDTO.setSuccess(false);
                            confirmForecastDTO.setErrorCode("OC-04-005-01-16-007");
                            confirmForecastDTO.setMessage("存在预报单确认状态为分析失败，不能回复确认");
                            confirmForecastDTOS.add(confirmForecastDTO);
                        } else if(ForecastDealStatusSEO.CONFIRM_ING.getStatus().equals(orderLine.getDealStatus())){
                            ConfirmForecastDTO confirmForecastDTO = new ConfirmForecastDTO();
                            confirmForecastDTO.setForecastOrderBizNO(orderLine.getMainOrderBizId());
                            confirmForecastDTO.setLineNo(orderLine.getSerialNumber());
                            confirmForecastDTO.setSuccess(false);
                            confirmForecastDTO.setErrorCode("OC-04-005-01-16-009");
                            confirmForecastDTO.setMessage("存在预报单确认状态为确认中，不能回复确认");
                            confirmForecastDTOS.add(confirmForecastDTO);
                        }
                    }
                });
            }

//            if (CollectionUtils.isEmpty(dissatisfyList)) {
//                shouldConfirmIdsAll.addAll(forecastOrderLineSDOList.stream().map(ForecastOrderLineSDO::getId).collect(Collectors.toList()));
//            }
        }

        //将预报订单状态推进到【确认中】
        com.epoch.app.crforecastsales.model.dto.ApiContext apiContext = request.getApiContext();
        if (CollectionUtils.isNotEmpty(shouldConfirmIdsAll)) {
            BatchUpdateForConfirmRequest batchUpdateForConfirmRequest = new BatchUpdateForConfirmRequest();
            batchUpdateForConfirmRequest.setDealStatus(ForecastDealStatusSEO.CONFIRM_ING.getStatus());
            batchUpdateForConfirmRequest.setModifierId(request.getOperatorId());
            batchUpdateForConfirmRequest.setModifierName(request.getOperatorName());
//            batchUpdateForConfirmRequest.set(request.getOperateCode());
            batchUpdateForConfirmRequest.setOrderLineIds(shouldConfirmIdsAll);
            forecastOrderLineWriteRepository.batchUpdateForConfirming(batchUpdateForConfirmRequest);
        }

        List<ForecastOrderEntity> forecastOrderEntityList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(forecastOrderEntities)) {
            forecastOrderEntityList = forecastOrderEntities.stream().filter(forecastOrderEntity -> {
                return forecastOrderSDOMap.containsKey(forecastOrderEntity.getForecastOrderSDO().getOrderBizId());
            }).collect(Collectors.toList());
        }
        log.info("forecastOrderEntityList结果:{}",JSON.toJSONString(forecastOrderEntityList));



        if (CollectionUtils.isNotEmpty(forecastOrderEntityList)) {
            Map<String, String> inventoryMap = syncQueryInventory(forecastOrderEntityList);

            for (ForecastOrderEntity forecastOrderEntity : forecastOrderEntityList) {
                ForecastOrderSDO forecastOrderSDO = forecastOrderEntity.getForecastOrderSDO();
                ErrorMessage errorMessage;
                ConfirmForecastDTO confirmForecastDTO = new ConfirmForecastDTO();
                confirmForecastDTO.setForecastOrderBizNO(forecastOrderSDO.getOrderBizId());
                confirmForecastDTO.setSuccess(Boolean.TRUE);
                List<Long> forecastLineIds = forecastOrderSDO.getForecastOrderLineSDOList().stream().map(ForecastOrderLineSDO::getId).collect(Collectors.toList());
                try (RedisLock lock = new RedisLock("REDIS_CACHE", "batch:" + forecastOrderEntity.getForecastOrderSDO().getId(), 0, 30 * 1000)) {
                    if (!lock.lock()) {
                        errorMessage = ErrorMessage.code("OTS-04-001-00-15-038", "该单据正在参与其它操作，请稍后重试");
                        confirmForecastDTO.setSuccess(Boolean.FALSE);
                        confirmForecastDTO.setMessage(errorMessage.getDisplayErrorMessage());
                        confirmForecastDTO.setErrorCode(errorMessage.getErrorCode());
                        confirmForecastDTOS.add(confirmForecastDTO);
                        continue;
                    }
                    // 创建销售订单
                    Result<List<BatchCreateOrderResponse>> confirmResult = syncConfirmForecastOrderByOne(request, forecastOrderEntity, inventoryMap,fulfillmentMap);
                    if (CollectionUtils.isNotEmpty(confirmResult.getResult())) {
                        integratedOrderList.addAll(confirmResult.getResult());
                        confirmForecastDTOS.add(confirmForecastDTO);
                    }
                } catch (FunctionException e) {
                    FailOrderRequest failOrderRequest = new FailOrderRequest();
                    failOrderRequest.setFailOrderIds(forecastLineIds);
                    failOrderRequest.setApiContext(apiContext);
                    failOrderRequest.setSequenceNo(request.getSequenceNo());
                    failOrderService.sendFailMsg(failOrderRequest);

                    confirmForecastDTO.setSuccess(Boolean.FALSE);
                    confirmForecastDTO.setMessage(e.getErrorMessage());
                    confirmForecastDTO.setErrorCode(e.getErrorCode());
                    confirmForecastDTOS.add(confirmForecastDTO);
                } catch (Exception e) {
                    log.error("ForecastOrderWriteServiceImpl#syncConfirmForecastBiz error", e);

                    confirmForecastDTO.setSuccess(Boolean.FALSE);
                    confirmForecastDTO.setMessage(e.getMessage());
                    confirmForecastDTO.setErrorCode("OC-04-005-01-16-001");
                    confirmForecastDTOS.add(confirmForecastDTO);
                }
            }

            if (CollectionUtils.isNotEmpty(integratedOrderList)) {
                List<TradeMessageSDO> tradeMessageSDOS = integratedOrderList.stream()
                        .map(BatchCreateOrderResponse::getTradeMessageSDO)
                        .filter(Objects::nonNull).distinct().collect(Collectors.toList());

                updateTask(integratedOrderList, taskId);

                Map<String, String> map = new HashMap<>();
                map.put("_CZ_KEY", BcOrderConstants.TENANT_ID());

                if (CollectionUtils.isNotEmpty(tradeMessageSDOS)) {
                    // 发送创建sap订单消息
                    String sequenceNo = request.getSequenceNo();
                    messageService.sendMessage("sale_order_message", "CR_SALEORDER_V2", "SaleBatchCreated", sequenceNo, sequenceNo, map);
                }

                // 发送订单创建成功消息
                List<String> salesOrderIds = integratedOrderList.stream()
                        .map(BatchCreateOrderResponse::getOrderId)
                        .filter(Objects::nonNull).distinct().collect(Collectors.toList());

                if (CollectionUtils.isNotEmpty(salesOrderIds)) {
                    List<OrderSDO> orderSDOS = new ArrayList<>();
                    for (String salesOrderId : salesOrderIds) {
                        log.info("ForecastOrderWriteServiceImpl#syncConfirmForecastBiz salesOrderId={}", salesOrderId);
                        QuerySingleRequest querySingleRequest = new QuerySingleRequest();
                        querySingleRequest.setMainOrderId(salesOrderId);
                        OrderSDO orderSDO = orderQueryService.querySingle(querySingleRequest);
                        if (Objects.isNull(orderSDO)) {
                            log.info("ForecastOrderWriteServiceImpl#syncConfirmForecastBiz querySingle is empty");
                            continue;
                        }
                        orderSDOS.add(orderSDO);
                    }

                    CommonAsyncMessageResponse message = new CommonAsyncMessageResponse();
                    message.setEventCode(InnerMessageEventEnum.SALES_ORDER_CREATED.getValue());
                    message.setEventName(InnerMessageEventEnum.SALES_ORDER_CREATED.getLabel());
                    message.setData(orderSDOS);
                    String messageString = JSON.toJSONString(message);
                    log.info("ForecastOrderWriteServiceImpl#syncConfirmForecastBiz sendMessage message={}", messageString);

                    // 发送MQ消息通知其他中心
                    messageService.sendMessage("sale_order_message", "CR_SALEORDER_V2", "SalesOrderEvent", UUID.randomUUID().toString(), messageString, map);
                }
            }

        }
        return Result.success(confirmForecastDTOS);
    }
    @Override
    @FacadeInvoker
    @Transactional(rollbackFor = Exception.class)
    public Result<List<ConfirmForecastDTO>> batchConfirmForecastGroupBiz(BatchConfirmForecastBiz batchConfirmForecastBiz){

        ConfirmForecastRequest request = new ConfirmForecastRequest();
        request.setIds(batchConfirmForecastBiz.getIds());
        request.setOperatorCode(batchConfirmForecastBiz.getModifierCode());
        request.setOperatorId(batchConfirmForecastBiz.getModifierId());
        request.setOperatorName(batchConfirmForecastBiz.getModifierName());
        log.info("request业务参数:{}", JSON.toJSONString(request));
        if (Objects.isNull(request) || CollectionUtils.isEmpty(request.getIds())) {
            return Result.fail("OC-04-005-01-16-002", "确认预报单为空!");
        }
        //根据入参单号查询预报单数据，并根据主订单进行分组
        List<ForecastOrderEntity> forecastOrderEntities = ForecastOrderFactory.confirmForecast(request);
        log.info("forecastOrderEntities结果:{}",JSON.toJSONString(forecastOrderEntities));
        //过滤预计回复数量为0，将确认状态改为确认中，避免页面没有及时刷新
        List<ConfirmForecastDTO> confirmForecastDTOList = new ArrayList<>();
        List<Long> shouldConfirmIdsAll = new ArrayList<>();
        List<ForecastOrderLineSDO> forecastOrderLineList = new ArrayList<>();
        Map<String, ForecastOrderSDO> forecastOrderSDOMap = new HashMap<>();
        for (ForecastOrderEntity forecastOrderEntity : forecastOrderEntities) {
            List<ForecastOrderLineSDO> forecastOrderLineSDOList = forecastOrderEntity.getForecastOrderSDO().getForecastOrderLineSDOList();
            List<ForecastOrderLineSDO> dissatisfyList = forecastOrderLineSDOList.stream()
                    .filter(o -> Objects.isNull(o.getPredictReplyAmount()) || o.getPredictReplyAmount() == 0 || !CAN_CONFIRM_FORECAST_STATUS.contains(o.getStatus()))
                    .collect(Collectors.toList());
            log.info("dissatisfyList结果:{}",JSON.toJSONString(dissatisfyList));
            if (CollectionUtils.isEmpty(dissatisfyList)) {
                shouldConfirmIdsAll.addAll(forecastOrderLineSDOList.stream().map(ForecastOrderLineSDO::getId).collect(Collectors.toList()));
                forecastOrderLineList.addAll(forecastOrderLineSDOList);
                forecastOrderSDOMap.put(forecastOrderEntity.getForecastOrderSDO().getOrderBizId(), forecastOrderEntity.getForecastOrderSDO());
            }else{
                dissatisfyList.stream().forEach(orderLine -> {
                    Integer predictReplayAmount = orderLine.getPredictReplyAmount() == null ? 0 : orderLine.getPredictReplyAmount();
                    if (!CAN_CONFIRM_FORECAST_STATUS.contains(orderLine.getStatus())){
                        ConfirmForecastDTO confirmForecastDTO = new ConfirmForecastDTO();
                        confirmForecastDTO.setForecastOrderBizNO(orderLine.getMainOrderBizId());
                        confirmForecastDTO.setLineNo(orderLine.getSerialNumber());
                        confirmForecastDTO.setSuccess(false);
                        confirmForecastDTO.setErrorCode("OC-01-001-01-16-053");
                        confirmForecastDTO.setMessage("当前操作与订单可执行操作不匹配");
                        confirmForecastDTOList.add(confirmForecastDTO);
                    } else if (predictReplayAmount == 0) {
                        ConfirmForecastDTO confirmForecastDTO = new ConfirmForecastDTO();
                        confirmForecastDTO.setForecastOrderBizNO(orderLine.getMainOrderBizId());
                        confirmForecastDTO.setLineNo(orderLine.getSerialNumber());
                        confirmForecastDTO.setSuccess(false);
                        confirmForecastDTO.setErrorCode("OC-04-005-01-16-002");
                        confirmForecastDTO.setMessage("预计回复数量须为正整数");
                        confirmForecastDTOList.add(confirmForecastDTO);
                    }
                });
            }
        }
        if (CollectionUtils.isNotEmpty(shouldConfirmIdsAll)) {
            List<ForecastOrderLineSDO> forecastOrderLineSDOList = new ArrayList<>();
            for(ForecastOrderLineSDO forecastOrderLine : forecastOrderLineList) {
                ForecastOrderLineSDO forecastOrderLineSDO = new ForecastOrderLineSDO();
                BeanUtils.copyProperties(forecastOrderLine, forecastOrderLineSDO);
                Integer actualTotalReplyAmount = forecastOrderLine.getActualTotalReplyAmount() == null ? 0 : forecastOrderLine.getActualTotalReplyAmount();
                forecastOrderLineSDO.setActualTotalReplyAmount(actualTotalReplyAmount + forecastOrderLine.getPredictReplyAmount());
                if(forecastOrderLineSDO.getActualTotalReplyAmount() >= Integer.valueOf(forecastOrderLine.getQuantity())){
                    forecastOrderLineSDO.setStatus(ForecastStatusEnum.COMPLETED.getNumValue());
                }else{
                    forecastOrderLineSDO.setStatus(ForecastStatusEnum.PARTIAL_REPLY.getNumValue());
                }
                forecastOrderLineSDO.setPredictReplyAmount(0);
                forecastOrderLineSDO.setDealStatus(ForecastDealStatusSEO.CONFIRM_ED.getStatus());
                forecastOrderLineSDO.setGmtModified(new Date());
                forecastOrderLineSDOList.add(forecastOrderLineSDO);
            }
            Boolean updateResult = forecastOrderLineWriteRepository.batchUpdateForecastOrderLine(forecastOrderLineSDOList);
            if(!updateResult){
                return Result.fail("OC-04-003-01-16-010", "预报订单行修改失败");
            } else{
                for(ForecastOrderLineSDO forecastOrderLine : forecastOrderLineList) {
                    ConfirmForecastDTO confirmForecastDTO = new ConfirmForecastDTO();
                    confirmForecastDTO.setForecastOrderBizNO(forecastOrderLine.getMainOrderBizId());
                    confirmForecastDTO.setLineNo(forecastOrderLine.getFrontLineNo());
                    confirmForecastDTO.setSuccess(true);
                    confirmForecastDTOList.add(confirmForecastDTO);
                }
            }
            Map<String, List<ForecastOrderLineSDO>> forecastOrderMap = forecastOrderLineSDOList.stream().collect(Collectors.groupingBy(ForecastOrderLineSDO::getMainOrderBizId));
            List<String> mainOrderIds = forecastOrderLineSDOList.stream().map(orderLine -> orderLine.getMainOrderId()).distinct().collect(Collectors.toList());
            BatchLoadListRequest batchLoadListRequest = new BatchLoadListRequest();
            batchLoadListRequest.setMainOrderIds(mainOrderIds);
            BatchLoadListResponse batchLoadListResponse = forecastOrderLineService.batchLoadList(batchLoadListRequest);
            log.info("batchLoadListRequest参数:{},batchLoadListResponse结果:{}",JSON.toJSONString(batchLoadListRequest), JSON.toJSONString(batchLoadListResponse));
            List<ForecastOrderLine> forecastOrderLineResult = batchLoadListResponse.getResult();
            Map<String, List<ForecastOrderLine>> forecastOrderLineMap = forecastOrderLineResult.stream().collect(Collectors.groupingBy(ForecastOrderLine::getMainOrderBizId));
            for(Map.Entry<String, List<ForecastOrderLineSDO>> orderLineEntry : forecastOrderMap.entrySet()){
                List<ForecastOrderLine> forecastOrderLines = forecastOrderLineMap.get(orderLineEntry.getKey());
                boolean status = forecastOrderLines.stream().anyMatch(orderLine -> ForecastStatusEnum.PARTIAL_REPLY.getNumValue().equals(orderLine.getStatus()));
                List<ForecastOrderLine> completeForecastOrderLines = forecastOrderLines.stream().filter(orderLine -> ForecastStatusEnum.COMPLETED.getNumValue().equals(orderLine.getStatus())).collect(Collectors.toList());
                List<ForecastOrderLine> waitForReplyForecastOrderLines = forecastOrderLines.stream().filter(orderLine -> ForecastStatusEnum.WAITING_FOR_REPLY.getNumValue().equals(orderLine.getStatus()) || ForecastStatusEnum.CANCELLED.getNumValue().equals(orderLine.getStatus())).collect(Collectors.toList());
                log.info("completeForecastOrderLines长度:{}",completeForecastOrderLines.size());
                log.info("waitForReplyForecastOrderLines长度:{}",waitForReplyForecastOrderLines.size());
                log.info("forecastOrderLineSDOS长度:{}",forecastOrderLines.size());
                ForecastOrderSDO forecastOrderSDO = forecastOrderSDOMap.get(orderLineEntry.getKey());
                if(status){
                    forecastOrderSDO.setStatus(ForecastStatusEnum.PARTIAL_REPLY.getNumValue());
                } else if(completeForecastOrderLines.size() > 0 && waitForReplyForecastOrderLines.size() > 0
                        && completeForecastOrderLines.size() + waitForReplyForecastOrderLines.size() == forecastOrderLines.size()){
                    forecastOrderSDO.setStatus(ForecastStatusEnum.PARTIAL_REPLY.getNumValue());
                } else {
                    forecastOrderSDO.setStatus(ForecastStatusEnum.COMPLETED.getNumValue());
                }
                forecastOrderSDO.setModifierCode(batchConfirmForecastBiz.getModifierCode());
                forecastOrderSDO.setModifierName(batchConfirmForecastBiz.getModifierName());
                forecastOrderSDO.setModifierId(batchConfirmForecastBiz.getModifierId());
                forecastOrderSDO.setGmtModified(new Date());
                boolean mainOrderResult = forecastOrderWriteRepository.modify(forecastOrderSDO);
                if(!mainOrderResult){
                    return Result.fail("OC-04-003-01-16-010", "预报订单修改失败");
                }
            }
        } /*else {
            return Result.fail("OC-04-003-01-16-010", "预报订单修改失败");
        }*/
        log.info("confirmForecastDTOList结果:{}",JSON.toJSONString(confirmForecastDTOList));
        return Result.success(confirmForecastDTOList);
    }

    private void updateTask(List<BatchCreateOrderResponse> integratedOrderList, String taskId) {
        //生成销售单对象
        Map<String, List<String>> confirmOrderMap = integratedOrderList.stream().map(BatchCreateOrderResponse::getTradeMessageSDO).map(TradeMessageSDO::getOrderSDO).collect(Collectors.toMap(OrderSDO::getId, p -> p.getOrderLineSDOS().stream().map(OrderLineSDO::getId).collect(Collectors.toList()), (v1, v2) -> v1));
        //生成销售单对象子单总条数
        AtomicInteger orderSizeAtomic = new AtomicInteger(0);
        confirmOrderMap.values().forEach(o -> orderSizeAtomic.getAndAdd(o.size()));

        MessageTask messageTask=new MessageTask();
        messageTask.setTaskId(Long.valueOf(taskId));
        messageTask.setExtraContent(JSON.toJSONString(confirmOrderMap));
        messageTask.setExtraCount(orderSizeAtomic.get());
        messageTask.setGmt_modified(new Date());
        messageTaskService.update(messageTask);
    }

    @NotNull
    private String startTask(ConfirmForecastRequest confirmForecastRequest, List<ForecastOrderEntity> forecastOrderEntities, MessageTaskTypeEnum taskTypeEnum) {
        //参加确认对象
        Map<String, List<Long>> confirmForecastMap = forecastOrderEntities.stream().map(ForecastOrderEntity::getForecastOrderSDO).collect(Collectors.toMap(ForecastOrderSDO::getId, p -> p.getForecastOrderLineSDOList().stream().map(ForecastOrderLineSDO::getId).collect(Collectors.toList()), (v1, v2) -> v1));
        //参加确认预报明细总条数
        Integer confirmSize = confirmForecastRequest.getIds().size();
        MessageTask messageTask = new MessageTask();
        messageTask.setBatchNo(confirmForecastRequest.getSequenceNo());
        messageTask.setMainContent(JSON.toJSONString(confirmForecastMap));
        messageTask.setMainCount(confirmSize);
        messageTask.setStatus(1);
        messageTask.setType(taskTypeEnum.getValue());
        messageTask.setGmt_create(new Date());
        messageTask.setGmt_modified(new Date());
        CreateResponse createResponse = messageTaskService.create(messageTask);
        return createResponse.getId();
    }

    private Map<String, String> syncQueryInventory(List<ForecastOrderEntity> forecastOrderEntities) {
        if (CollectionUtils.isEmpty(forecastOrderEntities)){
            return new HashMap<>();
        }
        //汇总查询确认库存
        Set<String> warehouseIds=new HashSet<>();
        Set<String> goodsIds=new HashSet<>();
        for (ForecastOrderEntity forecastOrderEntity : forecastOrderEntities) {
            warehouseIds.add(forecastOrderEntity.getForecastOrderSDO().getWareHouseCode());
            List<ForecastOrderLineSDO> forecastOrderLineSDOList = forecastOrderEntity.getForecastOrderSDO().getForecastOrderLineSDOList();
            //买品库存
            for (ForecastOrderLineSDO forecastOrderLineSDO : forecastOrderLineSDOList) {
                goodsIds.add(forecastOrderLineSDO.getScItemId());
            }
            //赠品库存
            for (ForecastOrderLineSDO forecastOrderLineSDO : forecastOrderLineSDOList) {
                Map features = forecastOrderLineSDO.getFeatures();
                List<ActivitySDO> activitySDOS = new ArrayList<>();
                if (Objects.nonNull(features) && Objects.nonNull(features.get(ForecastConstants.ACTIVITY_DETAILS))) {
                    activitySDOS = JSONObject.parseArray(JSON.toJSONString(features.get(ForecastConstants.ACTIVITY_DETAILS)), ActivitySDO.class);
                }
                for (ActivitySDO activitySDO : activitySDOS) {
                    if (Objects.nonNull(activitySDO) && Objects.nonNull(activitySDO.getIsSelect()) && activitySDO.getIsSelect()) {
                        List<GiftSDO> chooseGiftList = activitySDO.getChooseGiftList();
                        if (CollectionUtils.isNotEmpty(chooseGiftList)) {
                            List<String> goodsCodes = chooseGiftList.stream().map(GiftSDO::getScItemId).collect(Collectors.toList());

                            List<String> scItemIds = queryScItemId(goodsCodes);
                            goodsIds.addAll(scItemIds);
                        }
                    }
                }
            }
        }
        Map<String, String> inventoryMap = Maps.newHashMap();
        List<ForecastAnalysisInventoryRequest> availableInventoryQueryList = new ArrayList<>();
        // 获取可用库存
        ForecastAnalysisQueryInventoryRequest analysisQueryInventoryRequest = ForecastAnalysisQueryInventoryRequest.builder()
                .goodsIds(Arrays.asList(goodsIds.toArray()))
                .types(Lists.newArrayList(2, 3))
                .warehouseAreaIdList(Arrays.asList(warehouseIds.toArray()))
                .start(0)
                .limit(1000).build();

        Result<List<ForecastAnalysisInventoryRequest>> forecastAnalysisQueryInventory =
                crUnifiedInventoryService.forecastAnalysisQueryInventory(analysisQueryInventoryRequest);

        if (Objects.nonNull(forecastAnalysisQueryInventory)) {
            availableInventoryQueryList.addAll(forecastAnalysisQueryInventory.getResult());
            int total = forecastAnalysisQueryInventory.getTotal();
            if (total > 1000) {
                int totalPage = total / 1000;
                if (total % 1000 > 0) {
                    totalPage++;
                }
                for (int i = 1; i < totalPage; i++) {
                    analysisQueryInventoryRequest.setStart(i * 1000);
                    Result<List<ForecastAnalysisInventoryRequest>> pageResult =
                            crUnifiedInventoryService.forecastAnalysisQueryInventory(analysisQueryInventoryRequest);
                    if (Objects.nonNull(pageResult) && org.apache.commons.collections.CollectionUtils.isNotEmpty(pageResult.getResult())) {
                        availableInventoryQueryList.addAll(pageResult.getResult());
                    }
                }
            }
        }
//        List<WarehouseInventory> warehouseStockList = forecastOrderQueryRepository.getListWarehouseStock(getListWarehouseStockRequest);
        for (ForecastAnalysisInventoryRequest analysisInventoryRequest : availableInventoryQueryList) {
            String inventoryKey = String.format("%s-%s", analysisInventoryRequest.getWarehouseAreaId(), analysisInventoryRequest.getGoodsId());
            inventoryMap.put(inventoryKey, analysisInventoryRequest.getAvailableQuantity());
        }

        return inventoryMap;
    }

    @NotNull
    private List<String> queryScItemId(List<String> goodsCodes) {
        SearchScItemByDBWhenDegradedRequest searchScItemRequest = new SearchScItemByDBWhenDegradedRequest();
        searchScItemRequest.setPageSize(pageSize);
        Map<String, Object> searchReqDTO = new HashMap<>();
        searchReqDTO.put("outerIdList", goodsCodes);

        searchScItemRequest.setSearchReqDTO(searchReqDTO);
        //支持es降级查询db
        Result<List<ScItemSDO>> scItemListResult = baseDataService.searchScItemByDBWhenDegraded(searchScItemRequest);
        if (Objects.isNull(scItemListResult)||CollectionUtils.isEmpty(scItemListResult.getResult())) {
            throw new FacadeException("OTS-08-001-01-16-021");
        }
        List<String> scItemIds = scItemListResult.getResult().stream().map(ScItemSDO::getScItemId).distinct().collect(Collectors.toList());
        return scItemIds;
    }



    private Map<String, String> queryInventory(List<ForecastOrderEntity> forecastOrderEntities) {
        if (CollectionUtils.isEmpty(forecastOrderEntities)){
            return new HashMap<>();
        }
        //汇总查询确认库存
        Set<String> warehouseIds=new HashSet<>();
        Set<String> goodsIds=new HashSet<>();
        for (ForecastOrderEntity forecastOrderEntity : forecastOrderEntities) {
            warehouseIds.add(forecastOrderEntity.getForecastOrderSDO().getWareHouseCode());
            List<ForecastOrderLineSDO> forecastOrderLineSDOList = forecastOrderEntity.getForecastOrderSDO().getForecastOrderLineSDOList();
            //买品库存
            for (ForecastOrderLineSDO forecastOrderLineSDO : forecastOrderLineSDOList) {
                goodsIds.add(forecastOrderLineSDO.getScItemId());
            }
            //赠品库存
            for (ForecastOrderLineSDO forecastOrderLineSDO : forecastOrderLineSDOList) {
                Map features = forecastOrderLineSDO.getFeatures();
                List<ActivitySDO> activitySDOS = new ArrayList<>();
                if (Objects.nonNull(features) && Objects.nonNull(features.get(ForecastConstants.ACTIVITY_DETAILS))) {
                    activitySDOS = JSONObject.parseArray(JSON.toJSONString(features.get(ForecastConstants.ACTIVITY_DETAILS)), ActivitySDO.class);
                }
                for (ActivitySDO activitySDO : activitySDOS) {
                    if (Objects.nonNull(activitySDO) && Objects.nonNull(activitySDO.getIsSelect()) && activitySDO.getIsSelect()) {
                        List<GiftSDO> chooseGiftList = activitySDO.getChooseGiftList();
                        if (CollectionUtils.isNotEmpty(chooseGiftList)) {
                            goodsIds.addAll(chooseGiftList.stream().map(GiftSDO::getScItemId).collect(Collectors.toList()));
                        }
                    }
                }
            }
        }
        Map<String, String> inventoryMap = Maps.newHashMap();
        List<ForecastAnalysisInventoryRequest> availableInventoryQueryList = new ArrayList<>();
        // 获取可用库存
        ForecastAnalysisQueryInventoryRequest analysisQueryInventoryRequest = ForecastAnalysisQueryInventoryRequest.builder()
                .goodsIds(Arrays.asList(goodsIds.toArray()))
                .types(Lists.newArrayList(2, 3))
                .warehouseAreaIdList(Arrays.asList(warehouseIds.toArray()))
                .start(0)
                .limit(1000).build();

        Result<List<ForecastAnalysisInventoryRequest>> forecastAnalysisQueryInventory =
                crUnifiedInventoryService.forecastAnalysisQueryInventory(analysisQueryInventoryRequest);

        if (Objects.nonNull(forecastAnalysisQueryInventory)) {
            availableInventoryQueryList.addAll(forecastAnalysisQueryInventory.getResult());
            int total = forecastAnalysisQueryInventory.getTotal();
            if (total > 1000) {
                int totalPage = total / 1000;
                if (total % 1000 > 0) {
                    totalPage++;
                }
                for (int i = 1; i < totalPage; i++) {
                    analysisQueryInventoryRequest.setStart(i * 1000);
                    Result<List<ForecastAnalysisInventoryRequest>> pageResult =
                            crUnifiedInventoryService.forecastAnalysisQueryInventory(analysisQueryInventoryRequest);
                    if (Objects.nonNull(pageResult) && org.apache.commons.collections.CollectionUtils.isNotEmpty(pageResult.getResult())) {
                        availableInventoryQueryList.addAll(pageResult.getResult());
                    }
                }
            }
        }
//        List<WarehouseInventory> warehouseStockList = forecastOrderQueryRepository.getListWarehouseStock(getListWarehouseStockRequest);
        for (ForecastAnalysisInventoryRequest analysisInventoryRequest : availableInventoryQueryList) {
            String inventoryKey = String.format("%s-%s", analysisInventoryRequest.getWarehouseAreaId(), analysisInventoryRequest.getGoodsId());
            inventoryMap.put(inventoryKey, analysisInventoryRequest.getAvailableQuantity());
        }

        return inventoryMap;
    }

    @Override
    @FacadeInvoker
    public Result<Boolean> confirmUpdateDealForecast(ConfirmForecastRequest confirmForecastRequest) {
        log.info("ForecastOrderWriteServiceImpl|confirmUpdateDealForecast|批量确认|参数01 = {}", JSONObject.toJSONString(confirmForecastRequest));
        //根据主订单进行分组
        List<ForecastOrderEntity> forecastOrderEntities = ForecastOrderFactory.confirmForecast(confirmForecastRequest);
        if (CollectionUtils.isNotEmpty(forecastOrderEntities)) {
            for (ForecastOrderEntity forecastOrderEntity : forecastOrderEntities) {
                forecastOrderEntity.confirmUpdateDealForecast(JSONObject.parseObject(JSONObject.toJSONString(confirmForecastRequest.getApiContext()), ApiContext.class));
//                for (ForecastOrderLineSDO forecastOrderLineSDO : forecastOrderEntity.getForecastOrderSDO().getForecastOrderLineSDOList()) {
                    //添加日志
//                    LogUtils.printOperateLog(forecastOrderLineSDO.getMainOrderId(), ForecastOrderLogEnum.BATCH_CONFIRM.getForecastOrderLogValue(), "确认预报订单", loginUser);
                    //printOperateLog(forecastOrderLineSDO, forecastOrderLineSDO.getModifierName(), "确认预报订单",ForecastOrderLogEnum.BATCH_CONFIRM.getForecastOrderLogValue());
//                }

                //创建分析队列的表中数据
            }
        }

        return Result.success(true);
    }

    @Override
    @FacadeInvoker
    @Deprecated
    public Result<List<ConfirmForecastResponse>> batchConfirmCheckForecast(ConfirmForecastRequest confirmForecastRequest) {
        log.info("ForecastOrderWriteServiceImpl|confirmUpdateDealForecast|批量确认|检查入参02 = {}", JSONObject.toJSONString(confirmForecastRequest));
        List<ConfirmForecastResponse> confirmForecastResponses = new ArrayList<>();
        List<ForecastOrderEntity> forecastOrderEntities = ForecastOrderFactory.confirmForecast(confirmForecastRequest);
        ConfirmForecastResponse confirmForecastResponseSuccess = new ConfirmForecastResponse();
        ConfirmForecastResponse confirmForecastResponseFailed = new ConfirmForecastResponse();
        List<String> totalSuccessIds = new ArrayList<>();
        List<String> totalFailedIds = new ArrayList<>();
        for (ForecastOrderEntity forecastOrderEntity : forecastOrderEntities) {
            List<ConfirmForecastResponse> confirmForecastResponseYuan = forecastOrderEntity.confirmCheckForecast(confirmForecastRequest);
            if (CollectionUtils.isNotEmpty(confirmForecastResponseYuan)) {
                boolean existFail = false;
                for (ConfirmForecastResponse confirmForecastResponse : confirmForecastResponseYuan) {
                    //获取成功的子单id
                    //if ("1".equals(confirmForecastResponse.getTag())) {
                    //    List<String> ids = confirmForecastResponse.getIds();
                    //    totalSuccessIds.addAll(ids);
                    //}
                    if (("2".equals(confirmForecastResponse.getTag())
                            || "3".equals(confirmForecastResponse.getTag())) && CollectionUtils.isNotEmpty(confirmForecastResponse.getIds())) {
                        //List<String> ids = confirmForecastResponse.getIds();
                        //totalFailedIds.addAll(ids);
                        existFail = true;
                        break;
                    }
                }
                List<String> ids = forecastOrderEntity.getForecastOrderSDO()
                        .getForecastOrderLineSDOList()
                        .stream()
                        .map(ForecastOrderLineSDO::getId)
                        .map(String::valueOf)
                        .collect(Collectors.toList());
                if (!existFail) {
                    totalSuccessIds.addAll(ids);
                } else {
                    totalFailedIds.addAll(ids);
                }
            }
        }
        confirmForecastResponseSuccess.setIds(totalSuccessIds);
        confirmForecastResponseSuccess.setTag("1");
        confirmForecastResponseFailed.setTag("2");
        confirmForecastResponseFailed.setIds(totalFailedIds);
        confirmForecastResponses.add(confirmForecastResponseSuccess);
        confirmForecastResponses.add(confirmForecastResponseFailed);
        return Result.success(confirmForecastResponses);
    }

    @Override
    @FacadeInvoker
    public Result<ConfirmForecastResponse> batchConfirmCheckForecastNew(ConfirmForecastRequest confirmForecastRequest) {
        log.info("预报确认检查入参02 = {}", JSONObject.toJSONString(confirmForecastRequest));
        ConfirmForecastResponse response = new ConfirmForecastResponse();
        List<ForecastOrderEntity> forecastOrderEntities = ForecastOrderFactory.confirmForecast(confirmForecastRequest);

        Map<String, String> inventoryMap = queryInventory(forecastOrderEntities);
        Map<String, String> totalSuccessMap = new HashMap<>();
        Map<String, String> totalFailedMap = new HashMap<>();
        for (ForecastOrderEntity forecastOrderEntity : forecastOrderEntities) {
            ConfirmForecastResponse confirmForecastResponseYuan = forecastOrderEntity.confirmCheckForecastNew(confirmForecastRequest, inventoryMap);
            List<ForecastOrderLineSDO> forecastOrderLineSDOS = forecastOrderEntity.getForecastOrderSDO().getForecastOrderLineSDOList();
            for (ForecastOrderLineSDO forecastOrderLineSDO : forecastOrderLineSDOS) {
                String msg = "";
                if (confirmForecastResponseYuan != null) {
                    response.setMessage(confirmForecastResponseYuan.getMessage());
                    //成功的子单
                    if (MapUtils.isNotEmpty(confirmForecastResponseYuan.getSuccessOrderLineMap())) {
                        Map<String, String> successMap = confirmForecastResponseYuan.getSuccessOrderLineMap();
                        totalSuccessMap.putAll(successMap);
                        if (successMap.containsKey(forecastOrderLineSDO.getId().toString())) {
                            msg = successMap.get(forecastOrderLineSDO.getId().toString());
                        }
                    }
                    //失败的子单
                    if (MapUtils.isNotEmpty(confirmForecastResponseYuan.getFailOrderLineMap())) {
                        Map<String, String> failedMap = confirmForecastResponseYuan.getFailOrderLineMap();
                        totalFailedMap.putAll(failedMap);
                        if (failedMap.containsKey(forecastOrderLineSDO.getId().toString())) {
                            msg = failedMap.get(forecastOrderLineSDO.getId().toString());
                        }
                        //只有失败的情况下走更新状态
                        forecastOrderEntity.backForecastUpdate(forecastOrderLineSDO, msg);
                    }

                }

            }
        }
        response.setSuccessOrderLineMap(totalSuccessMap);
        response.setFailOrderLineMap(totalFailedMap);

        log.info("批量确认-检查响应结果:" + JSON.toJSONString(response));
        return Result.success(response);
    }

    @Override
    @FacadeInvoker(remark = "批量确认")
    @EpochTransactional(appCode = "cr_forecast_sales", dataSourceCode = "cr_ots")
    public Result<Boolean> batchConfirmUpdateForecast(ConfirmForecastRequest confirmForecastRequest) {
        LoginUser loginUser = epochLoginUserService.getLoginUser();
        confirmForecastRequest.setOperatorName(loginUser.getRealName());
        boolean isSuccess = true;
        log.info("预报确认修改订单状态入参03 = {}", JSONObject.toJSONString(confirmForecastRequest));
        List<BatchCreateOrderRequest> confirmForecastStatuses = confirmForecastRequest.getConfirmForecastStatuses();
        if (CollectionUtils.isEmpty(confirmForecastStatuses)) {
            throw new FacadeException("OTS-04-001-00-15-047");
        }
        for (BatchCreateOrderRequest confirmForecastStatus : confirmForecastStatuses) {
            ForecastOrderEntity forecastOrderEntity = ForecastOrderFactory.confirmForecastStatus(confirmForecastStatus, confirmForecastRequest);
            // 更新预报单状态
            isSuccess = forecastOrderEntity.confirmForecastStatus();
            //LogUtils.printOperateLog(forecastOrderEntity.getForecastOrderSDO().getId(),ForecastOrderLogEnum.REPLY.getForecastOrderLogValue(),"回复预报订单");
        }

        return Result.success(isSuccess);
    }

    @Override
    @FacadeInvoker
    //@EpochTransactional(appCode = "cr_forecast_sales", dataSourceCode = "cr_ots")  批量拒绝时单个子单拒绝消息已经发出、此时异常回滚没有意义
    public Result<Boolean> batchRefuseForecast(RefuseForecastRequest refuseForecastRequest) {
        Result<Boolean> result = batchRefuseForecastV2(refuseForecastRequest);
        //result空值判断
        if (Objects.isNull(result) || !result.isSuccess() || !result.getResult()) {
            log.error("ForecastOrderWriteServiceImpl#batchRefuseForecast_fail");
        }
        return result;
        /**
         *批量拒绝  根据id load出来数据 进行修改
         */
        /*log.info("预报拒绝入参 = {}", JSONObject.toJSONString(refuseForecastRequest));
        LoginUser loginUser = epochLoginUserService.getLoginUser();
        try {
            if (CollectionUtils.isEmpty(refuseForecastRequest.getRefuseForecastDetailRequests())) {
                throw new FunctionException("OTS-04-001-00-15-008");
            }
            List<ForecastOrderLineEntity> forecastOrderLineEntities = ForecastOrderFactory.batchRefuseForecast(refuseForecastRequest.getRefuseForecastDetailRequests());
            List<ForecastOrderLineSDO> forecastOrderLineSDOList = new ArrayList<>();
            for (ForecastOrderLineEntity forecastOrderLineEntity : forecastOrderLineEntities) {
                ForecastOrderLineSDO forecastOrderLineSDO = forecastOrderLineEntity.getForecastOrderLineSDO();
                forecastOrderLineSDOList.add(forecastOrderLineSDO);
                OpLogModel.OpLogModelBuilder<String> builder = OpLogModel.builder();
                OpLogModel<String> opLogModel = builder.build();
                opLogModel.setModuleName(ModuleEnum.FORECAST_SALES.getModuleName());
                opLogModel.setModuleId(String.valueOf(ModuleEnum.FORECAST_SALES.getModuleId()));
                opLogModel.setObjectId(forecastOrderLineEntity.getForecastOrderLineSDO().getMainOrderId());
                opLogModel.setObjectName("id");
                opLogModel.setOperateType(OperateType.EDIT.getOperateType());
                opLogModel.setOperatorType(OperatorType.USER.getOperatorType());
                log.asyncMonitorObjectChangeV2(opLogModel);

                boolean analysis = forecastOrderLineWriteRepository.updateForAnalysis(forecastOrderLineSDO);
                if (analysis) {
                    String mainOrderId = forecastOrderLineSDO.getMainOrderId();
                    CountRefuseLineResponse countRefuseLineResponse = forecastOrderLineQueryService.countRefuseLine(new CountRefuseLineRequest() {{
                        setMainOrderId(mainOrderId);
                    }});
                    ForecastOrderSDO load = forecastOrderQueryRepository.load(mainOrderId);
//                    SearchForecastOrderRequest searchForecastOrderRequest=new SearchForecastOrderRequest();
//                    searchForecastOrderRequest.setId(mainOrderId);
//                    List<Integer> list=new ArrayList<>();
//                    list.add(2);
//                    list.add(3);
//                    searchForecastOrderRequest.setDetailStatusList(list);
                    ForecastOrderLineSDO orderLineSDO = new ForecastOrderLineSDO();
                    orderLineSDO.setMainOrderId(mainOrderId);
                    List<ForecastOrderLineSDO> forecastOrderLineSDOS = forecastOrderLineQueryRepository.queyrLineDetailList(orderLineSDO);
                    boolean bo = forecastOrderLineSDOS.stream().anyMatch(fo -> (fo.getStatus().intValue() == ForecastStatusEnum.WAITING_FOR_REPLY.getNumValue() || fo.getStatus().intValue() == ForecastStatusEnum.PARTIAL_REPLY.getNumValue()));
//                    Thread.sleep(200);//修改状态后再查询会导致部分回复无法转为全部回复
//                    Result<List<QueryForecastLineResponse>> listResult = forecastOrderLineQueryRepository.pageQuery(searchForecastOrderRequest);


                    if (bo) {
                        load.setStatus(ForecastStatusEnum.PARTIAL_REPLY.getNumValue());
                    } else {
                        load.setStatus(ForecastStatusEnum.COMPLETED.getNumValue());
                    }

                    if (Objects.nonNull(countRefuseLineResponse) && Objects.nonNull(countRefuseLineResponse.getRefuseType())) {
                        load.setRefuseStatus(countRefuseLineResponse.getRefuseType());
                    }
                    boolean b = forecastOrderWriteRepository.modifyForecast(load);
                    LogUtils.printOperateLog(load.getId(), ForecastOrderLogEnum.EDIT.getForecastOrderLogValue(), "编辑预报订单", loginUser);
                    //add by 皓晖 at 20211217 for 批量拒绝预报订单发消息 begin
                    this.sendMessage("ForecastRefused", forecastOrderLineSDO);
                    //add by 皓晖 at 20211217 for 批量拒绝预报订单发消息 end
                }
            }
            return Result.success(true);
        } catch (Exception e) {
            log.error("批量拒绝错误参数：", e);
            throw new FunctionException("OTS-04-001-00-15-009");
        }*/
    }

    private Result<Boolean> batchRefuseForecastV2(RefuseForecastRequest refuseForecastRequest) {
        /**
         *批量拒绝  根据id load出来数据 进行修改
         */
        log.info("预报拒绝入参 = {}", JSONObject.toJSONString(refuseForecastRequest));
        LoginUser loginUser = epochLoginUserService.getLoginUser();
        if (CollectionUtils.isEmpty(refuseForecastRequest.getRefuseForecastDetailRequests())) {
            return Result.fail("OTS-04-001-00-15-008", "子单号不能为空");
        }
        Map<String, List<ForecastOrderLineSDO>> refuseForecastMap = ForecastOrderFactory.batchRefuseForecastNew(refuseForecastRequest.getRefuseForecastDetailRequests());
        boolean res = true;
        ErrorMessage errorMessage = new ErrorMessage();
        for (String orderId : refuseForecastMap.keySet()) {
            if (CollectionUtils.isEmpty(refuseForecastMap.get(orderId))) {
                continue;
            }
            // todo 和批量确认的key一样，防止并发
            String lockKey = "batch:" + orderId;
            try (RedisLock lock = new RedisLock("REDIS_CACHE", lockKey, 0, 30 * 1000)) {
                if (!lock.lock()) {
                    log.error("batchRefuseForecastV2加锁失败:" + lockKey);
                    errorMessage = ErrorMessage.code("OTS-04-001-00-15-038", "有部分单据正在参与其它操作，请稍后重试");
                    res = false;
                    continue;
                }
                for (ForecastOrderLineSDO orderLine : refuseForecastMap.get(orderId)) {
                    boolean analysis = forecastOrderLineWriteRepository.updateForAnalysis(orderLine);
                    // todo 后续可以优化，将更新主单状态放子单外部
                    if (analysis) {
                        String mainOrderId = orderLine.getMainOrderId();
                        CountRefuseLineResponse countRefuseLineResponse = forecastOrderLineQueryService.countRefuseLine(new CountRefuseLineRequest() {{
                            setMainOrderId(mainOrderId);
                        }});
                        ForecastOrderSDO load = forecastOrderQueryRepository.load(mainOrderId);
                        ForecastOrderLineSDO orderLineSDO = new ForecastOrderLineSDO();
                        orderLineSDO.setMainOrderId(mainOrderId);
                        List<ForecastOrderLineSDO> forecastOrderLineSDOS = forecastOrderLineQueryRepository.queyrLineDetailList(orderLineSDO);
                        boolean bo = forecastOrderLineSDOS.stream().anyMatch(fo -> (
                                fo.getStatus().intValue() == ForecastStatusEnum.WAITING_FOR_REPLY.getNumValue()
                                        || fo.getStatus().intValue() == ForecastStatusEnum.PARTIAL_REPLY.getNumValue()
                        ));

                        if (bo) {
                            load.setStatus(ForecastStatusEnum.PARTIAL_REPLY.getNumValue());
                        } else {
                            load.setStatus(ForecastStatusEnum.COMPLETED.getNumValue());
                        }

                        if (Objects.nonNull(countRefuseLineResponse) && Objects.nonNull(countRefuseLineResponse.getRefuseType())) {
                            load.setRefuseStatus(countRefuseLineResponse.getRefuseType());
                        }
                        boolean b = forecastOrderWriteRepository.modifyForecast(load);
                        LogUtils.printOperateLog(load, ForecastOrderLogEnum.CLOSE.getForecastOrderLogValue(), "关闭预报订单", loginUser);
                        //add by 皓晖 at 20211217 for 批量拒绝预报订单发消息 begin
                        this.sendMessage("ForecastRefused", orderLine);
                        //add by 皓晖 at 20211217 for 批量拒绝预报订单发消息 end
                    }
                }
            } catch (Exception e) {
                log.error("ForecastOrderWriteServiceImpl#batchRefuseForecastV2_fail");
                log.error("batchRefuseForecastNew|批量拒绝时发生异常:", e);
                errorMessage = ErrorMessage.code("OTS-04-001-00-15-038", "有部分单据拒绝失败，请稍后重试");
                res = false;
            }
        }
        if (!res) {
            //add data content
            return Result.fail(false, errorMessage.getErrorCode(), errorMessage.getErrorMessage());
        }
        return Result.success(true);
    }

    /**
     * 预报订单取消、预报订单拒绝发送消息
     */
    private void sendMessage(String tag, ForecastOrderLineSDO forecastOrderLineSDO) {
        try {
            String key = forecastOrderLineSDO.getId().toString();
            this.messageService.sendMessage("forecast_send_message", "CR_FORECAST_V2",
                    tag, key, JSON.toJSONString(forecastOrderLineSDO));
        } catch (Exception e) {
            log.error("预报订单发送消息失败", e);
        }
    }

    @Override
    @FacadeInvoker
    public Result<Boolean> updateForecastSubmit(ModifyForecastOrderRequest modifyForecastOrderRequest) {
        //获取主订单Id
        String id = modifyForecastOrderRequest.getForecastOrderSDOList().get(0).getId();
        //主订单部分数据进行更新
        if (StringUtils.isNotEmpty(id)) {
            //调用load方法查询 预报订单数据
            List<ForecastOrderEntity> forecastOrderEntities = ForecastOrderFactory.modifyDraft(modifyForecastOrderRequest);
            for (ForecastOrderEntity forecastOrderEntity : forecastOrderEntities) {
                forecastOrderEntity.modifyDetailForecast();
            }
        }
        return Result.success(true);
    }

    @Override
    @FacadeInvoker
    public Result<Boolean> batchActivityCheckForecast(ForecastOrderActivityRequest forecastOrderActivityRequest) {
        //根据传入Ids进行单据参数封装  更改订单处理状态
        List<ForecastOrderEntity> forecastOrderEntities = ForecastOrderFactory.checkActivityForecast(forecastOrderActivityRequest);
        boolean isSuccess = true;
        for (ForecastOrderEntity forecastOrderEntity : forecastOrderEntities) {

            //按照主单维度进行查询活动
            isSuccess = forecastOrderEntity.activityUpdateDealForecast(JSONObject.parseObject(JSONObject.toJSONString(forecastOrderActivityRequest.getApiContext()),
                    ApiContext.class));

            //将数据的信息插入分析队列的表中
            List<DealLineSDO> collect = Nullable.stream(forecastOrderEntity.getForecastOrderSDO().getForecastOrderLineSDOList()).map(forecastOrderLineSDO -> {
                DealLineSDO dealLineSDO = new DealLineSDO();
                dealLineSDO.setForecastOrderLineId(forecastOrderLineSDO.getId().toString());
                dealLineSDO.setDealStatus(ForecastDealStatusSEO.CHECk_ED.getStatus());
                dealLineSDO.setDealType(ForecastDealTypeSEO.CHECK_ACTIVITIES.getDealTypeCode().toString());
                dealLineSDO.setModifierName(forecastOrderLineSDO.getModifierName());
                dealLineSDO.setModifierId(forecastOrderLineSDO.getModifierId());
                dealLineSDO.setDealTime(new Date());
                Date now = new Date();
                SimpleDateFormat f = new SimpleDateFormat("yyyyMMddhhmmss");
                String format = f.format(now);//20211015030520
                dealLineSDO.setBatchNumber(format);
                return dealLineSDO;
            }).collect(Collectors.toList());
            //创建分析队列的表中数据
            boolean b = dealLineWriteRepository.batchCreate(collect);
        }
        return Result.success(isSuccess);
    }

    /**
     * 确认活动
     *
     * @param forecastUpdateActivityRequest 活动更新请求
     * @return
     */
    @Override
    @FacadeInvoker
    public Result<Boolean> updateActivityForecast(ForecastUpdateActivityRequest forecastUpdateActivityRequest) {
        List<ForecastOrderActivityRequest> forecastOrderActivityRequestList = forecastUpdateActivityRequest.getForecastOrderActivityRequestList();
        boolean isSuccess = true;
        if (CollectionUtils.isNotEmpty(forecastOrderActivityRequestList)) {

            long l1 = System.currentTimeMillis();
            //批量查询子单
            List<String> orderLineIds = forecastOrderActivityRequestList.stream().map(ForecastOrderActivityRequest::getForecastOrderLineId).collect(Collectors.toList());
            int inputIdPage = (orderLineIds.size() % 1000 == 0) ? (orderLineIds.size() / 1000) : (orderLineIds.size() / 1000+1);
            List<ForecastOrderLineSDO> forecastOrderLineSDOS=new ArrayList<>();
            for (int i = 0; i < inputIdPage; i++) {
                int min = Math.min((i + 1) * 1000, orderLineIds.size());
                List<String> subList = orderLineIds.subList(i * 1000, min);
                PageResult<List<ForecastOrderLineSDO>> listPageResult = forecastOrderLineQueryRepository.batchLoadList(subList);
                if (Objects.nonNull(listPageResult)&&CollectionUtils.isNotEmpty(listPageResult.getContent())){
                    forecastOrderLineSDOS.addAll(listPageResult.getContent());
                }
            }
            long l2 = System.currentTimeMillis();
            log.info("批量查询子单耗时"+(l2-l1));
            Map<String, ForecastOrderLineSDO> forecastOrderLineMap = Nullable.stream(forecastOrderLineSDOS).collect(Collectors.toMap(o->String.valueOf(o.getId()), Function.identity()));

            //批量查询主单
            List<String> mainOrderIds = Nullable.stream(forecastOrderLineSDOS).map(ForecastOrderLineSDO::getMainOrderId).distinct().collect(Collectors.toList());
            List<ForecastOrderSDO> forecastOrderSDOS = forecastOrderQueryRepository.batchQueryForecastOrder(mainOrderIds);
            Map<String, ForecastOrderSDO> forecastOrderSDOMap = Nullable.stream(forecastOrderSDOS).collect(Collectors.toMap(ForecastOrderSDO::getId, Function.identity()));

            long l3 = System.currentTimeMillis();
            log.info("批量查询主单单耗时"+(l3-l2));
            for (ForecastOrderActivityRequest forecastOrderActivityRequest : forecastOrderActivityRequestList) {
                ForecastOrderEntity forecastOrderEntity = ForecastOrderFactory.updateActivityForecast(forecastOrderActivityRequest,forecastOrderLineMap,forecastOrderSDOMap);
//            //模型转换
                isSuccess = forecastOrderEntity.updateActivityForecast();
            }
            long l4 = System.currentTimeMillis();
            log.info("循环更新耗时"+(l4-l3));
        }

        return Result.success(isSuccess);
    }

    /**
     * 确认活动
     *
     * @param forecastUpdateActivityRequest 活动更新请求
     * @return
     */
    @Override
    @FacadeInvoker
    public Result<Boolean> updateActivityForecastObsolete(ForecastUpdateActivityRequestObsolete forecastUpdateActivityRequest) {
        List<ForecastOrderActivityObsoleteRequest> forecastOrderActivityRequestList = forecastUpdateActivityRequest.getForecastOrderActivityRequestList();
        boolean isSuccess = true;
        if (CollectionUtils.isNotEmpty(forecastOrderActivityRequestList)) {

            long l1 = System.currentTimeMillis();
            //批量查询子单
            List<String> orderLineIds = forecastOrderActivityRequestList.stream().map(ForecastOrderActivityObsoleteRequest::getForecastOrderLineId).collect(Collectors.toList());
            int inputIdPage = (orderLineIds.size() % 1000 == 0) ? (orderLineIds.size() / 1000) : (orderLineIds.size() / 1000+1);
            List<ForecastOrderLineSDO> forecastOrderLineSDOS=new ArrayList<>();
            for (int i = 0; i < inputIdPage; i++) {
                int min = Math.min((i + 1) * 1000, orderLineIds.size());
                List<String> subList = orderLineIds.subList(i * 1000, min);
                PageResult<List<ForecastOrderLineSDO>> listPageResult = forecastOrderLineQueryRepository.batchLoadList(subList);
                if (Objects.nonNull(listPageResult)&&CollectionUtils.isNotEmpty(listPageResult.getContent())){
                    forecastOrderLineSDOS.addAll(listPageResult.getContent());
                }
            }
            long l2 = System.currentTimeMillis();
            log.info("批量查询子单耗时"+(l2-l1));
            Map<String, ForecastOrderLineSDO> forecastOrderLineMap = Nullable.stream(forecastOrderLineSDOS).collect(Collectors.toMap(o->String.valueOf(o.getId()), Function.identity()));

            //批量查询主单
            List<String> mainOrderIds = Nullable.stream(forecastOrderLineSDOS).map(ForecastOrderLineSDO::getMainOrderId).distinct().collect(Collectors.toList());
            List<ForecastOrderSDO> forecastOrderSDOS = forecastOrderQueryRepository.batchQueryForecastOrder(mainOrderIds);
            Map<String, ForecastOrderSDO> forecastOrderSDOMap = Nullable.stream(forecastOrderSDOS).collect(Collectors.toMap(ForecastOrderSDO::getId, Function.identity()));

            long l3 = System.currentTimeMillis();
            log.info("批量查询主单单耗时"+(l3-l2));
            for (ForecastOrderActivityObsoleteRequest forecastOrderActivityRequest : forecastOrderActivityRequestList) {
                ForecastOrderEntity forecastOrderEntity = ForecastOrderFactory.updateActivityForecastObsolete(forecastOrderActivityRequest,forecastOrderLineMap,forecastOrderSDOMap);
//            //模型转换
                isSuccess = forecastOrderEntity.updateActivityForecast();
            }
            long l4 = System.currentTimeMillis();
            log.info("循环更新耗时"+(l4-l3));
        }

        return Result.success(isSuccess);
    }

    @Override
    @FacadeInvoker
    public Result<Boolean> deleteActivityForecast(DeleteActivityForecastRequest deleteActivityForecastRequest) {
        //拼装参数
        ForecastOrderEntity forecastOrderEntity = ForecastOrderFactory.deleteActivityForecast(deleteActivityForecastRequest);
        Boolean aBoolean = forecastOrderEntity.deleteActivityForecast();
        return Result.success(aBoolean);
    }

    @Override
    @FacadeInvoker
    public Result<SummaryForecastOrderResponse> summaryForecastOrder(SummaryForecastOrderRequest summaryForecastOrderRequest) {
        SummaryForecastOrderResponse summaryForecastOrderResponse = new SummaryForecastOrderResponse();
        if (CollectionUtils.isEmpty(summaryForecastOrderRequest.getIds())) {
            return Result.fail("OTS-04-001-00-15-008", "子单号不能为空");
        }
        List<String> ids = summaryForecastOrderRequest.getIds();
        PageResult<List<ForecastOrderLineSDO>> pageResult = forecastOrderLineQueryRepository.batchLoadList(ids);
        if (pageResult == null || CollectionUtils.isEmpty(pageResult.getContent())) {
            return Result.fail("OTS-04-001-00-15-009", "未查询到子单信息");
        }
        //根据发货仓进行分组
        Map<String, List<ForecastOrderLineSDO>> collect = Nullable.stream(pageResult.getContent()).collect(Collectors.groupingBy(ForecastOrderLineSDO::getWarehouseArea));
        if (collect.keySet().size() > 1) {
            return Result.fail("OTS-04-001-00-15-016", "所有单据必须为同一发货仓");
        }
        //乐观锁更新单据状态，防止并发
        UpdateCollectStatusRequest updateCollectStatusRequest = new UpdateCollectStatusRequest();
        updateCollectStatusRequest.setNewCollectStatus(1);
        updateCollectStatusRequest.setOldCollectStatus(0);
        updateCollectStatusRequest.setIds(ids);
        if (!forecastOrderLineWriteRepository.batchUpdateCollectStatus(updateCollectStatusRequest)) {
            return Result.fail("OTS-04-001-00-15-007", "批量更新子单汇总状态失败");
        }
        try {
            ForecastOrderEntity forecastOrderEntity = buildForecastOrderEntity(pageResult.getContent());
            String code = forecastOrderEntity.summaryForecastOrder();
            summaryForecastOrderResponse.setCode(code);
            return Result.success(summaryForecastOrderResponse);
        } catch (Exception e) {
            updateCollectStatusRequest.setNewCollectStatus(0);
            updateCollectStatusRequest.setOldCollectStatus(1);
            forecastOrderLineWriteRepository.batchUpdateCollectStatus(updateCollectStatusRequest);
            log.error("汇总预报单创建调拨单失败，原因=" + e.getMessage(), e);
            return Result.fail("OTS-04-001-00-15-026", e.getMessage());
        }
    }

    private ForecastOrderEntity buildForecastOrderEntity(List<ForecastOrderLineSDO> forecastOrderLineList) {
        List<ForecastOrderLineSDO> newForecastOrderLineSDOS = new ArrayList<>();
        Map<String, List<ForecastOrderLineSDO>> scitemMap = forecastOrderLineList.stream().collect(Collectors.groupingBy(ForecastOrderLineSDO::getScItemId));
        for (String scitemId : scitemMap.keySet()) {
            //获取出每种商品对应的子订单
            int countNumber = 0;
            List<ForecastOrderLineSDO> forecastOrderLineSDOS = scitemMap.get(scitemId);
            for (ForecastOrderLineSDO forecastOrderLineSDO : forecastOrderLineSDOS) {
                //将所有的数量装换成为库存单位数量  并累加
                if (StringUtils.isEmpty(forecastOrderLineSDO.getQuantity()) || StringUtils.isEmpty(forecastOrderLineSDO.getUnitConvert())) {
                    throw new FunctionException("OTS-04-001-00-15-019");
                }
                if ((!ObjectUtils.isEmpty(forecastOrderLineSDO.getQuantity()) && !ObjectUtils.isEmpty(forecastOrderLineSDO.getUnitConvert()))) {
                    int number = Integer.parseInt(forecastOrderLineSDO.getQuantity()) * Integer.parseInt(forecastOrderLineSDO.getUnitConvert());
                    countNumber += number;
                }
            }
            ForecastOrderLineSDO newForecastOrderLineSDO = new ForecastOrderLineSDO();
            BeanUtils.copyProperties(forecastOrderLineSDOS.get(0), newForecastOrderLineSDO);
            newForecastOrderLineSDO.setQuantity(String.valueOf(countNumber));
            newForecastOrderLineSDOS.add(newForecastOrderLineSDO);
        }
        ForecastOrderSDO forecastOrderSDO = forecastOrderQueryRepository.load(forecastOrderLineList.get(0).getMainOrderId());
        forecastOrderSDO.setForecastOrderLineSDOList(newForecastOrderLineSDOS);
        return ForecastOrderEntity.of(forecastOrderSDO);
    }

    @Override
    @FacadeInvoker
    public Result<List<OrderSDO>> batchCreateOrder(CretateOrderParamRequest cretateOrderParamRequest) {
        if (CollectionUtils.isEmpty(cretateOrderParamRequest.getIds())) {
            throw new FunctionException("OTS-04-001-00-15-004");
        }
        List<ForecastOrderEntity> forecastOrderEntities = ForecastOrderFactory.batchCreateForecastOrder(cretateOrderParamRequest.getIds());
        String sequenceNo = cretateOrderParamRequest.getSequenceNo();
        List<OrderSDO> orderSDOS = ForecastOrderFactory.batchCreateOrder(forecastOrderEntities, sequenceNo);
        //不知道为什么价update
//        for(ForecastOrderEntity forecastOrderEntity:forecastOrderEntities){
//            forecastOrderEntity.updateForecastOrderLine();
//        }
        return Result.success(orderSDOS);


    }

    @Override
    @FacadeInvoker
    public Result<List<ForecastOrderExportRequest>> createForecastOrderExport(CreateForecastOrderExportRequest createForecastOrderExportRequest) {
        LoginUser loginUser = epochLoginUserService.getLoginUser();
        Set<String> organizationCodeSet = Sets.newHashSet();
        Set<String> productGroupCodeSet = Sets.newHashSet();
        Set<String> channelCodeSet = Sets.newHashSet();
        Set<String> scItemCodeSet = Sets.newHashSet();
        Set<String> receiveAddressCodeSet = Sets.newHashSet();
        Set<String> saleUnitSet = Sets.newHashSet();
        Set<String> transportModeCodeSet = Sets.newHashSet();
        Set<String> wareHouseCodeSet = Sets.newHashSet();
        List<ForecastOrderExportRequest> orderLineToQueryActive = Lists.newArrayList();
        long batchNo = System.currentTimeMillis();
        // 入参中行数据的集合
        List<ForecastOrderExportRequest> orderExportRequestList = Optional.ofNullable(createForecastOrderExportRequest.getCreateForecastOrderExportRequest()).orElse(Lists.newArrayList());
        int size = orderExportRequestList.size();
        for (int i = 0; i < size; i++) {
            ForecastOrderExportRequest record = orderExportRequestList.get(i);
            if (record == null) {
                continue;
            }
            //导入数据去空格
            trim(record,Lists.newArrayList("remark","detailRemark","customerReferenceNo"));
            // 增加导入的时候的顺序字段
            Map reqFeatureMap = record.getFeatures();
            if (reqFeatureMap == null) {
                reqFeatureMap = Maps.newHashMap();
                record.setFeatures(reqFeatureMap);
            }
            reqFeatureMap.put(ForecastConstants.FORECAST_ORDER_IMPORT_INDEX, String.format("%s_%s", batchNo, String.format("%04d", i)));

            // 必填校验
            //预报订单类型校验
            if (StringUtils.isBlank(record.getOrderType())) {
                record.setErrorMessage("预报订单类型未填写");
                continue;
            }
            //单据原因校验 不为空时校验
            if(StringUtils.isNotBlank(record.getCreateReason())){
                DocumentReasonEnum documentReasonEnum= DocumentReasonEnum.of(record.getCreateReason());
                if(documentReasonEnum==null){
                    record.setErrorMessage("单据原因匹配失败");
                    continue;
                }
            }
            // 校验组织编码
            if (StringUtils.isBlank(record.getOrganizationCode())) {
                record.setErrorMessage("销售组织未填写");
                continue;
            } else {
                organizationCodeSet.add(StringUtils.trim(record.getOrganizationCode()));
            }

            //校验货品组信息
            if (StringUtils.isBlank(record.getProductGroupCode())) {
                record.setErrorMessage("货品组未填写");
                continue;
            } else {
                productGroupCodeSet.add(StringUtils.trim(record.getProductGroupCode()));
            }

            //校验渠道编码
            if (StringUtils.isBlank(record.getChannelCode())) {
                record.setErrorMessage("业务渠道未填写");
                continue;
            } else {
                channelCodeSet.add(StringUtils.trim(record.getChannelCode()));
            }

            //校验货品
            if (StringUtils.isBlank(record.getScItemId())) {
                record.setErrorMessage("货品未填写");
                continue;
            } else {
                scItemCodeSet.add(StringUtils.trim(record.getScItemId()));
            }

//            if (StringUtils.isBlank(record.getCustomerReferenceNo())) {
//                record.setErrorMessage("客户参考号未填写");
//                continue;
//            }

            //校验客户地址信息
            if (StringUtils.isBlank(record.getReceiveAddressCode())) {
                record.setErrorMessage("客户送达方未填写");
                continue;
            } else {
                receiveAddressCodeSet.add(StringUtils.trim(record.getReceiveAddressCode()));
            }

            if (StringUtils.isBlank(record.getSaleUnit())) {
                record.setErrorMessage("销售单位未填写");
                continue;
            } else {
                saleUnitSet.add(StringUtils.trim(record.getSaleUnit()));
            }

            //运输方式进行校验
            if (StringUtils.isNotBlank(record.getTransportModeCode())) {
                transportModeCodeSet.add(StringUtils.trim(record.getTransportModeCode()));
            }

            //校验发货仓库信息
            if (StringUtils.isBlank(record.getWareHouseCode())) {
                record.setErrorMessage("逻辑发货仓库未填写");
                continue;
            } else {
                wareHouseCodeSet.add(StringUtils.trim(record.getWareHouseCode()));
            }

            //校验预报数量   不能为空，是数字，不能大于多少
            if (StringUtils.isBlank(record.getQuantity()) || !StringUtils.isNumeric(record.getQuantity())) {
                record.setErrorMessage("数量未填写或填写内容不是数字");
                continue;
            }

            int quantityTmp = Integer.parseInt(record.getQuantity());
            if (quantityTmp <= 0 || quantityTmp > 10000000) {
                record.setErrorMessage("预报数量应在0到10000000之间");
                continue;
            }

            //校验备注信息   长度小于50
            if (StringUtils.isNotBlank(record.getRemark()) && record.getRemark().length() > 256) {
                record.setErrorMessage("备注信息长度不能超过255个字");
                continue;
            }

            //校验备注信息   长度小于30
            if (StringUtils.isNotBlank(record.getCustomerReferenceNo()) && record.getCustomerReferenceNo().length() > 30) {
                record.setErrorMessage("客户采购号长度不能超过30个字");
                continue;
            }
            if (Objects.nonNull(record.getCustomerExpectTDate())){
                if (Objects.equals(DateUtils.string2Date("9999-01-01 00:00:00"), record.getCustomerExpectTDate())) {
                    record.setErrorMessage("期望交货日期格式不正确");
                    continue;
                }
                Date firstTime = DateUtils.getFirstTime(new Date());
                if (record.getCustomerExpectTDate().compareTo(firstTime)<0){
                    record.setErrorMessage("期望交货日期不能小于当天");
                    continue;
                }
            }else {
                record.setErrorMessage("期望交货日期不能为空");
                continue;
            }

            //校验备注信息   长度小于50
            if (StringUtils.isNotBlank(record.getDetailRemark()) && record.getDetailRemark().length() > 256) {
                record.setErrorMessage("备注详情信息长度不能超过255个字");
                continue;
            }

            if (Objects.equals(record.getOrderType(), SaleOrderTag.REPLENISH_FORECAST.getCode())) {
                if (StringUtils.isBlank(record.getActivityCode())) {
                    record.setErrorMessage("补货活动ID必填");
                    continue;
                }
                if (StringUtils.isBlank(record.getActivityProjectCodeproject())) {
                    record.setErrorMessage("补货项目号必填");
                    continue;
                }
                if (StringUtils.isNotBlank(record.getActivityCode()) && StringUtils.isNotBlank(record.getActivityProjectCodeproject())) {
                    orderLineToQueryActive.add(record);
                }
            }

            //非补货订单不能填写补货活动信息
            if (!Objects.equals(record.getOrderType(), SaleOrderTag.REPLENISH_FORECAST.getCode())) {
                if (StringUtils.isNotBlank(record.getActivityCode())) {
                    record.setErrorMessage("非补货订单不能填写补货活动ID");
                    continue;
                }
                if (StringUtils.isNotBlank(record.getActivityProjectCodeproject())) {
                    record.setErrorMessage("非补货订单不能填写补货项目号");
                }
            }
        }
        // 获取登陆人 信息
        EmployeeGetCurrentLoginResponse employeeGetCurrentLoginResponse = bcOrderService.employeeGetCurrentLogin();
        // 批量获取相关依赖的数据
        // 组织
        Map<String, List<OrganizationSDO>> organizationMap = batchQeuryOrgMap(organizationCodeSet);
        // 货品组
        Map<String, ScItemGroupResponse> productGroupMap = batchQueryProductGroup(productGroupCodeSet);
        //货品经营范围
        List<ScItemManageRange> scItemManageRanges = searchScItemManageRange();

        List<String> ids = new ArrayList<>();
        organizationMap.entrySet().forEach(stringListEntry -> ids.addAll(stringListEntry.getValue().stream().map(OrganizationSDO::getId).collect(Collectors.toList())));
        // 渠道
        Map<String, OrganizationChannelRelationSDO> channelMap = batchQueryChannelMap(channelCodeSet, ids);
        // 货品
        List<ScItemSDO> scItemAllStatusList = batchQueryItemsAllStatus(scItemCodeSet);
        Map<String, List<ScItemSDO>> scItemAllStatusMap = scItemAllStatusList.stream().collect(Collectors.groupingBy(ScItemSDO::getOuterId));
        List<ScItemSDO> scItemList = scItemAllStatusList.stream().filter(x->x.getStatus()!=null && x.getStatus()==1).collect(Collectors.toList());
        Map<String, List<ScItemSDO>> scItemMap = scItemList.stream().collect(Collectors.groupingBy(ScItemSDO::getOuterId));

        // 送达方
        Map<String, List<CustomerAddressSDO>> receiveAddressMap = batchQueryReceiveAddressMap(receiveAddressCodeSet, employeeGetCurrentLoginResponse);
        // 货品单位
        Map<String, List<ScItemUnit>> saleUnitMap = batchQuerySaleUnitMap(saleUnitSet);
        // 发货仓库
        Map<String, List<WarehouseInfo>> warehouseMap = batchQueryWareHouse(wareHouseCodeSet);
        // 运输方式
        Map<String, String> transportModeCodeMap = batchQueryTransportMode(transportModeCodeSet);
        // 查询活动  客户参考号+货品id 唯一key变更至 forecastOrder.getOrderType() + forecastOrder.getOrganizationCode() + forecastOrder.getProductGroupCode() + forecastOrder.getChannelCode()
        //                    + forecastOrder.getReceiveAddressCode() + forecastOrder.getCustomerReferenceNo()
        Map<String, List<ActivityInfoResponse>> activityInfoMap = activityQueryCode(orderLineToQueryActive,employeeGetCurrentLoginResponse);
        /*//活动id  和活动项目号
        Map<String, List<String>> activityIdMap=new HashMap<>();
        for (Map.Entry<String, List<ActivityInfoResponse>> stringListEntry : activityInfoMap.entrySet()) {
            List<String> activityTermId=Lists.newArrayList();
            List<ActivityInfoResponse> activityInfoResponses = stringListEntry.getValue();
            activityInfoResponses.stream().forEach(it->{Nullable.stream(it.getActivityTermList()).forEach(x->{activityTermId.add(x.getActivityTermId());});});
            activityIdMap.put(stringListEntry.getKey(),activityTermId);
        }*/
        //订单类型枚举 SaleOrderTag
        List<String> typeList = Lists.newArrayList();
        typeList.add(SaleOrderTag.STD_FORECAST.getCode());
        typeList.add(SaleOrderTag.CAR_FORECAST.getCode());
        typeList.add(SaleOrderTag.REPLENISH_FORECAST.getCode());
        for (ForecastOrderExportRequest record : orderExportRequestList) {
            if (StringUtils.isNotBlank(record.getErrorMessage())) {
                continue;
            }
            //订单类型枚举 SaleOrderTag
            if (!typeList.contains(StringUtils.trim(record.getOrderType()))) {
                record.setErrorMessage("订单类型无效");
                continue;
            }
            // 数据有效性校验
            if (MapUtils.isEmpty(organizationMap) || !organizationMap.containsKey(StringUtils.trim(record.getOrganizationCode()))) {
                record.setErrorMessage("销售组织无效");
                continue;
            }

            if (MapUtils.isEmpty(productGroupMap) || !productGroupMap.containsKey(StringUtils.trim(record.getProductGroupCode()))) {
                record.setErrorMessage("货品组无效");
                continue;
            }

            if (MapUtils.isEmpty(channelMap) || !channelMap.containsKey(StringUtils.trim(record.getChannelCode()))) {
                record.setErrorMessage("业务渠道无效");
                continue;
            }

            if (MapUtils.isEmpty(scItemAllStatusMap) || !scItemAllStatusMap.containsKey(StringUtils.trim(record.getScItemId()))) {
                record.setErrorMessage("该货品主数据系统中不存在，请确认后再重新导入");
                continue;
            }
            if (MapUtils.isEmpty(scItemMap) || !scItemMap.containsKey(StringUtils.trim(record.getScItemId()))) {
                record.setErrorMessage("该货品主数据系统中处于禁用状态，请启用后再重新导入");
                continue;
            }

            //校验分子公司货品经营范围
            if (CollectionUtils.isNotEmpty(scItemManageRanges)){
                String checkMsg = checkScItemManageRange(scItemManageRanges, record.getScItemId());
                if (checkMsg !=null){
                    record.setErrorMessage(checkMsg);
                    continue;
                }
            }

            if (MapUtils.isEmpty(receiveAddressMap) || !receiveAddressMap.containsKey(StringUtils.trim(record.getReceiveAddressCode()))) {
                record.setErrorMessage("客户送达方无效");
                continue;
            }
            List<CustomerAddressSDO> customerAddressSDOS = Optional.ofNullable(receiveAddressMap.get(record.getReceiveAddressCode())).orElse(Lists.newArrayList());
            if (CollectionUtils.isEmpty(customerAddressSDOS)){
                record.setErrorMessage("客户送达方无效");
                continue;
            }
            //校验客户送达方是否有业务员
            List<CustomerAddressSDO> customerAddressSDOList = customerAddressSDOS.stream().filter(customerAddressSDO ->
                    StringUtils.isNotBlank(customerAddressSDO.getPrincipal())
            ).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(customerAddressSDOList) || Objects.isNull(customerAddressSDOList.get(0))) {
                record.setErrorMessage("客户送达方无对应的业务员");
                continue;
            }
            // 校验仓库信息 填写以填写为准，否则系统根据供货关系默认
            if (org.apache.commons.lang.StringUtils.isBlank(record.getWareHouseCode())) {
                CustomerAddressSDO customerAddressSDO = customerAddressSDOS.get(0);
                // 销售部门 需要 作为入参 更改供货关系customerCode为addressCode
                QueryAllocateRelationForOrderRequest request = QueryAllocateRelationForOrderRequest.builder()
                        .organizationCode(record.getOrganizationCode())
                        .saleChannelCode(customerAddressSDO.getOrgSaleChannelCode())
                        .addressCode(customerAddressSDO.getAddressCode())
                        .saleDepartmentCode(customerAddressSDO.getOrgSaleDepartmentCode()).build();
                Result<List<AllocateRelationSDO>> listResult = allocateRelationReadService.queryAllocateRelationForOrder(request);
                if (!ObjectUtils.isEmpty(listResult) && !CollectionUtils.isEmpty(listResult.getResult())) {
                    record.setWareHouseCode(listResult.getResult().get(0).getWareHouseCode());
                }
            }
            //补货活动时，校验活动项目号，活动id是否有效
            if (record.getOrderType().equals(SaleOrderTag.REPLENISH_FORECAST.getCode())) {
                String key = record.getOrderType() + record.getOrganizationCode() + record.getProductGroupCode() + record.getChannelCode() + record.getReceiveAddressCode() + record.getCustomerReferenceNo() + record.getScItemId();
                List<ActivityInfoResponse> activityInfoResponses1 = activityInfoMap.get(key);
                List<String> collect = Nullable.stream(activityInfoResponses1).map(ActivityInfoResponse::getActivityId).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(activityInfoResponses1) || !collect.contains(StringUtils.trim(record.getActivityCode()))) {
                    record.setErrorMessage("补货活动ID无效");
                    continue;
                }
                List<String> activityProjectIds = Lists.newArrayList();
                for (ActivityInfoResponse activityInfoResponse : activityInfoResponses1) {
                    Nullable.stream(activityInfoResponse.getActivityTermList()).forEach(it -> {
                        activityProjectIds.add(it.getActivityTermId());
                    });
                }
                if (CollectionUtils.isEmpty(activityProjectIds)
                        || !activityProjectIds.contains(StringUtils.trim(record.getActivityProjectCodeproject()))) {
                    record.setErrorMessage("补货活动项目号无效");
                    continue;
                }
            }

            if (MapUtils.isEmpty(warehouseMap) || !warehouseMap.containsKey(StringUtils.trim(record.getWareHouseCode()))) {
                record.setErrorMessage("逻辑发货仓库无效");
                continue;
            }

            if (StringUtils.isNotBlank(record.getSaleUnit()) && (MapUtils.isEmpty(saleUnitMap) || !saleUnitMap.containsKey(StringUtils.trim(record.getSaleUnit())))) {
                record.setErrorMessage("销售单位无效");
                continue;
            }

            if (StringUtils.isNotBlank(record.getTransportModeCode()) && (MapUtils.isEmpty(transportModeCodeMap) || !transportModeCodeMap.containsKey(StringUtils.trim(record.getTransportModeCode())))) {
                record.setErrorMessage("运输方式无效");
                continue;
            }
        }

        List<ForecastOrderExportRequest> validList = Lists.newArrayList();
        Function<ForecastOrderExportRequest, String> groupKey = req -> req.getOrderType() + req.getOrganizationCode() + req.getProductGroupCode() + req.getChannelCode() + req.getReceiveAddressCode() + req.getCustomerReferenceNo();

        Map<String, List<ForecastOrderExportRequest>> validRecordGroup = orderExportRequestList.stream().collect(Collectors.groupingBy(groupKey, LinkedHashMap::new, Collectors.toList()));
        for (String addressCode : validRecordGroup.keySet()) {
            List<ForecastOrderExportRequest> list = Optional.ofNullable(validRecordGroup.get(addressCode)).orElse(Lists.newArrayList());
            boolean validFlag = true;
            for (ForecastOrderExportRequest orderExportRequest : list) {
                if (StringUtils.isNotBlank(orderExportRequest.getErrorMessage())) {
                    validFlag = false;
                }
            }
            if (validFlag) {
                validList.addAll(list);
            }else {
                for (ForecastOrderExportRequest forecastOrderExportRequest : list) {
                    if (StringUtils.isBlank(forecastOrderExportRequest.getErrorMessage())){
                        forecastOrderExportRequest.setErrorMessage("同主单下存在校验不通过的子单行");
                    }
                }
            }
        }

        List<Future<Boolean>> createFutureList = Lists.newArrayList();
        Map<String, List<ForecastOrderExportRequest>> checkValidRecordGroup = validList.stream().collect(Collectors.groupingBy(groupKey, LinkedHashMap::new, Collectors.toList()));
        //excel分组Map反转顺序
        checkValidRecordGroup = reverseLinkedHashMap(checkValidRecordGroup);
        for (Map.Entry<String, List<ForecastOrderExportRequest>> mainForecastOrderEntry : checkValidRecordGroup.entrySet()) {
            //按excel导入顺序，创建预报订单
            String nextStringSequence = customSequenceAccessor.getNextStringSequence("cr_forecast_sales", "forecastOrderId");
            for (ForecastOrderExportRequest request : mainForecastOrderEntry.getValue()) {
                request.setOrderBizId(nextStringSequence);
            }

            Future<Boolean> createForecastOrderFeature = forecastSaleTaskExecutor.submit(() -> {
                try {
                    executeOne(createForecastOrderExportRequest, loginUser, organizationMap, productGroupMap, channelMap, scItemMap, receiveAddressMap, warehouseMap, transportModeCodeMap, activityInfoMap, mainForecastOrderEntry);
                } catch (Exception e) {
                    log.error(e, "预报订单导入， 主单创建失败, entry:{}", JSON.toJSONString(mainForecastOrderEntry));
                    return false;
                }

                return true;
            });

            createFutureList.add(createForecastOrderFeature);
        }

        for (Future<Boolean> booleanFuture : createFutureList) {
            try {
                log.info("批量导入创单结果：", booleanFuture.get());
            } catch (Exception e) {
                log.error("批量导入创单线程异常：", e);
            }
        }

        return Result.success(orderExportRequestList);
    }

    private Map<String, List<ForecastOrderExportRequest>> reverseLinkedHashMap(Map<String, List<ForecastOrderExportRequest>> map){
        ListIterator<Map.Entry<String, List<ForecastOrderExportRequest>>> listIterator = new ArrayList<>(map.entrySet()).listIterator(map.size());
        Map<String, List<ForecastOrderExportRequest>> result = new LinkedHashMap();
        while (listIterator.hasPrevious()) {
            Map.Entry<String,List<ForecastOrderExportRequest>> entry = listIterator.previous();
            result.put(entry.getKey(), entry.getValue());
        }
        return result;
    }

    private void executeOne(CreateForecastOrderExportRequest createForecastOrderExportRequest, LoginUser loginUser, Map<String, List<OrganizationSDO>> organizationMap, Map<String, ScItemGroupResponse> productGroupMap, Map<String, OrganizationChannelRelationSDO> channelMap, Map<String, List<ScItemSDO>> scItemMap, Map<String, List<CustomerAddressSDO>> receiveAddressMap, Map<String, List<WarehouseInfo>> warehouseMap, Map<String, String> transportModeCodeMap, Map<String, List<ActivityInfoResponse>> activityInfoMap, Map.Entry<String, List<ForecastOrderExportRequest>> mainForecastOrderEntry) {
        ForecastOrderSDO sdo = new ForecastOrderSDO();

        //String nextStringSequence = customSequenceAccessor.getNextStringSequence("cr_forecast_sales", "forecastOrderId");
        List<ForecastOrderExportRequest> forecastOrderExportRequests = Optional.ofNullable(mainForecastOrderEntry.getValue()).orElse(Lists.newArrayList());
        Date customerExpectTDate = forecastOrderExportRequests.get(0).getCustomerExpectTDate();
        //默认当天
        if (Objects.isNull(customerExpectTDate) || Objects.equals(customerExpectTDate, "")) {
            customerExpectTDate = new Date();
        }
        sdo.setOrderType(forecastOrderExportRequests.get(0).getOrderType());
        sdo.setRemark(forecastOrderExportRequests.get(0).getRemark());
        sdo.setOrderBizId(forecastOrderExportRequests.get(0).getOrderBizId());
        sdo.setStatus(ForecastStatusEnum.DRAFT.getNumValue());//需要变成待回复  ，先变成待提交，再调提交接口变成待回复  (可能导入订单状态直接为待提交，提交操作失败，需要手动提交)
        sdo.setCreateReason(forecastOrderExportRequests.get(0).getCreateReason());
        sdo.setOrganizationCode(forecastOrderExportRequests.get(0).getOrganizationCode());
        sdo.setProductGroupCode(forecastOrderExportRequests.get(0).getProductGroupCode());
        sdo.setChannelCode(forecastOrderExportRequests.get(0).getChannelCode());
        sdo.setReceiveAddressCode(forecastOrderExportRequests.get(0).getReceiveAddressCode());
        sdo.setTransportModeCode(forecastOrderExportRequests.get(0).getTransportModeCode());
        sdo.setWareHouseCode(forecastOrderExportRequests.get(0).getWareHouseCode());
        sdo.setCreatorId(createForecastOrderExportRequest.getCreateId());
        sdo.setCreatorName(createForecastOrderExportRequest.getCreateName());
        sdo.setGmtCreate(new Date());
        sdo.setCustomerExpectTDate(customerExpectTDate);
        sdo.setCustomerReferenceNo(forecastOrderExportRequests.get(0).getCustomerReferenceNo());

        // 获取渠道匹配的客户地址
        CustomerAddressSDO aimCustomerAddress = null;
        List<CustomerAddressSDO> customerAddressSDOS = Optional.ofNullable(receiveAddressMap.get(sdo.getReceiveAddressCode())).orElse(Lists.newArrayList());


        for (CustomerAddressSDO customerAddressSDO : customerAddressSDOS) {
            if (customerAddressSDO.getChannelCode().equals(sdo.getChannelCode())) {
                aimCustomerAddress = customerAddressSDO;
                break;
            }
        }

        if (aimCustomerAddress == null) {
            List<ForecastOrderExportRequest> targetValues = Optional.ofNullable(mainForecastOrderEntry.getValue()).orElse(Lists.newArrayList());
            for (ForecastOrderExportRequest targetValue : targetValues) {
                targetValue.setErrorMessage("收货地址&渠道不匹配");
            }
            return;
        }
        CustomerAddressSDO customerAddressSDO = null;
        //过滤掉没有业务员的客户收货地址
        List<CustomerAddressSDO> customerAddressSDOList = customerAddressSDOS.stream().filter(addressSDO ->
                StringUtils.isNotBlank(addressSDO.getPrincipal())
        ).collect(Collectors.toList());

        for (CustomerAddressSDO address : customerAddressSDOList) {
            if (address.getChannelCode().equals(sdo.getChannelCode())) {
                customerAddressSDO = address;
                break;
            }
        }
        if (customerAddressSDO == null) {
            List<ForecastOrderExportRequest> targetValues = Optional.ofNullable(mainForecastOrderEntry.getValue()).orElse(Lists.newArrayList());
            for (ForecastOrderExportRequest targetValue : targetValues) {
                targetValue.setErrorMessage("客户送达方没有分派销售负责人");
            }
            return;
        }

//        customerAddressSDO = aimCustomerAddress;
        sdo.setCustomerCode(customerAddressSDO.getCustomerCode());
        sdo.setCustomerName(customerAddressSDO.getCustomerName());
//            sdo.setOrganizationCode(customerAddressSDO.getOrgSaleOrganizationCode());
//            sdo.setOrganizationName(customerAddressSDO.getOrgSalesOrganizationName());
        //add by myw
        sdo.setBisUnitCode(customerAddressSDO.getOrgBussinessUnitCode());
        sdo.setDepartmentCode(customerAddressSDO.getOrgSaleDepartmentCode());
        sdo.setDepartmentName(customerAddressSDO.getOrgSalesDepartmentName());
        sdo.setSaleChannelCode(customerAddressSDO.getOrgSaleChannelCode());
        sdo.setSaleChannelName(customerAddressSDO.getOrgSalesChannelName());
        sdo.setChannelCode(customerAddressSDO.getChannelCode());
        sdo.setSalesmanCode(customerAddressSDO.getPrincipal());
        sdo.setSalesmanName(customerAddressSDO.getPrincipalName());
        sdo.setChannelName(customerAddressSDO.getChannelName());
        sdo.setContact(customerAddressSDO.getContactName());
        sdo.setContactPhone(customerAddressSDO.getCellphoneNumber());
        sdo.setReceiveDetailAddress(customerAddressSDO.getAddressName());
        sdo.setProductGroupCode(customerAddressSDO.getItemGroup());
        sdo.setVaildBeginTime(new Date());
        sdo.setProductGroupName(customerAddressSDO.getItemGroupName());

        sdo.setWareHouseName(warehouseMap.get(sdo.getWareHouseCode()).get(0).getName());
        sdo.setWareHouseCode(warehouseMap.get(sdo.getWareHouseCode()).get(0).getId());

        //通过导入参数外部编码查询名称和内部编码
        sdo.setOrganizationName(organizationMap.get(sdo.getOrganizationCode()).get(0).getName());
        sdo.setOrganizationCode(organizationMap.get(sdo.getOrganizationCode()).get(0).getId());

        sdo.setChannelName(channelMap.get(sdo.getChannelCode()).getName());
        sdo.setChannelCode(channelMap.get(sdo.getChannelCode()).getCode());

        sdo.setDepartmentCode(customerAddressSDO.getOrgSaleDepartmentCode());
        sdo.setDepartmentName(customerAddressSDO.getOrgSalesDepartmentName());

        sdo.setProductGroupName(productGroupMap.get(sdo.getProductGroupCode()).getName());
        sdo.setProductGroupCode(productGroupMap.get(sdo.getProductGroupCode()).getCode());

        //调用查询客户信息
        if (StringUtils.isNotBlank(sdo.getCustomerCode())) {
            CustomerRequest request = new CustomerRequest();
            request.setCode(sdo.getCustomerCode());
            Result<CustomerSDO> result = customerQueryService.queryCustomer(request);
            if (result.isSuccess() && Objects.nonNull(result.getResult()) && Objects.nonNull(result.getResult().getCode())) {
                sdo.setCustomerName(result.getResult().getName());
                sdo.setCustomerCode(result.getResult().getCode());
            }
        }

        sdo.setTransportModeName(transportModeCodeMap.get(sdo.getTransportModeCode()));

        //导入的预报单增加source 数据来源到features
        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put(ForecastConstants.OS, "import");
        sdo.setFeatures(hashMap);
        List<ForecastOrderLineSDO> forecastOrderLineSDOS = new ArrayList<>();
        sdo.setForecastOrderLineSDOList(forecastOrderLineSDOS);

        boolean createFlag = true;
        int i = 1;
        for (ForecastOrderExportRequest it : forecastOrderExportRequests) {

            Map map = new HashMap();
            map.put(ForecastConstants.ACTIVITY_NUMBER, it.getActivityProjectCodeproject());
            map.put(ForecastConstants.FORECAST_ORDER_IMPORT_INDEX, Optional.ofNullable(it.getFeatures()).orElse(Maps.newHashMap()).getOrDefault(ForecastConstants.FORECAST_ORDER_IMPORT_INDEX, ""));
            ForecastOrderLineSDO build = ForecastOrderLineSDO.builder()
                    .scItemId(it.getScItemId())
                    .quantity(it.getQuantity())
                    .saleUnit(it.getSaleUnit())
                    .serialNumber(String.valueOf(i * 10))
                    .status(2)
                    .warehouseArea(sdo.getWareHouseCode())
                    .mainOrderBizId(sdo.getOrderBizId())
                    .detailRemark(it.getDetailRemark())
                    .saleUnitCode(it.getSaleUnit().trim())
                    .activityCode(it.getActivityCode())
                    //.mainOrderId(save)
                    .dealStatus(ForecastDealStatusSEO.WAITING_DEAL.getStatus())
                    .customerCode(sdo.getCustomerCode())
                    .customerName(sdo.getCustomerName())
                    .activityCode(it.getActivityCode())
                    .activityNumber(it.getActivityProjectCodeproject())
                    .features(map).build();
            i++;
            //补货预报订单加活动信息  且匹配到活动信息
            ForecastOrderExportRequest activityTempOrder = forecastOrderExportRequests.get(0);
            String key = activityTempOrder.getOrderType() + activityTempOrder.getOrganizationCode() + activityTempOrder.getProductGroupCode() + activityTempOrder.getChannelCode() + activityTempOrder.getReceiveAddressCode() + activityTempOrder.getCustomerReferenceNo() + activityTempOrder.getScItemId();
            if (it.getOrderType().equals(SaleOrderTag.REPLENISH_FORECAST.getCode()) && CollectionUtils.isNotEmpty(activityInfoMap.get(key))) {

                List<ActivityInfoResponse> activityInfoResponses = activityInfoMap.get(key);
                List<ActivityInfoResponse> realActivityList = Nullable.stream(activityInfoResponses).filter(e -> Objects.equals(e.getActivityId(), it.getActivityCode())).collect(Collectors.toList());
                ActivityInfoResponse activityInfoResponse = realActivityList.get(0);//补货活动匹配到的活动
                Nullable.stream(activityInfoResponse.getActivityTermList()).forEach(active -> {
                    if (Objects.equals(active.getActivityTermId(), it.getActivityProjectCodeproject())) {
                        build.setActivityCode(activityInfoResponse.getActivityId());
                        build.setActivityName(activityInfoResponse.getActivityNoteName());
                        build.setIntensityOfActivityDesc(active.getIntensityOfActivityDesc());
                        build.setActivityNumber(active.getActivityTermId());
                        build.setActivityVersion(active.getVersion());
                        build.setActivityRemainingFee(active.getActivityRemainingFee());
                        build.setActivityRemainingQuantity(active.getActivityRemainingQuantity());
                    }
                });
            }
            ScItemSDO scItemSDO = scItemMap.get(build.getScItemId()).get(0);
            build.setScItemOutCode(scItemSDO.getOuterId());
            build.setScItemTitle(scItemSDO.getTitle());
            build.setScItemId(scItemSDO.getScItemId());
            build.setGoodsCode(scItemSDO.getOuterId());
            Map<String, String> features = scItemSDO.getFeatures();
            if (MapUtils.isNotEmpty(features)) {
                String unitName = features.get("unit");
                String unitCode = features.get("unitName");
                if (StringUtils.isNotBlank(unitName)) {
                    build.setInventoryUnit(unitName);
                }
                if (StringUtils.isNotBlank(unitCode)) {
                    build.setInventoryUnitCode(unitCode);
                }
                build.setCategoryCode(features.get("category"));
                build.setCategoryDesc(features.get("categoryDesc"));
                build.setCategoryChildCode(features.get("categoryChildCode"));
                build.setCategoryChildDesc(features.get("categoryChildDesc"));
            }

            QuerySaleUnitRequest querySaleUnitRequest = QuerySaleUnitRequest.builder().scItemId(scItemSDO.getScItemId()).build();
            querySaleUnitRequest.setInventoryUnit(build.getInventoryUnit());
            querySaleUnitRequest.setInventoryUnitCode(build.getInventoryUnitCode());
            querySaleUnitRequest.setUnitConvert("1");
            Result<List<SelectCombox>> querySaleUnitList = forecastOrderLineQueryService.querySaleUnitList(querySaleUnitRequest);
            if (querySaleUnitList.isSuccess() && Objects.nonNull(querySaleUnitList.getResult())) {
                List<SelectCombox> result = querySaleUnitList.getResult();
                Map<String, SelectCombox> unitMap = new HashMap<>();
                Nullable.stream(result).forEach(t -> {
                    unitMap.put(t.getValue(), t);
                });
                SelectCombox selected = unitMap.get(build.getSaleUnitCode());
                if (selected != null) {
                    build.setSaleUnit(selected.getLabel());
                    build.setUnitConvert(selected.getExt());
                }

                SelectCombox inventoryMap = unitMap.get(build.getInventoryUnitCode());
                if (inventoryMap != null) {
                    build.setInventoryUnit(inventoryMap.getLabel());
                }
            }

            List<SubOrderInfo> forecastOrderLine = queryOrderLinePrice(sdo, build);

            Map<String, Object> dailyInventory = queryDailyInv(sdo, build);
            if ((boolean) dailyInventory.getOrDefault("limitSwitch", false)) {
                if (StringUtils.isNotBlank(String.valueOf(dailyInventory.get("dailyInventory")))) {
                    BigDecimal dailyInventory1 = new BigDecimal(String.valueOf(dailyInventory.get("dailyInventory"))).setScale(3, RoundingMode.DOWN);
                    BigDecimal bigDecimal = new BigDecimal(build.getQuantity()).setScale(3, RoundingMode.DOWN);
                    if (bigDecimal.compareTo(dailyInventory1) > 0) {
                        for (ForecastOrderExportRequest forecastOrderExportRequest : mainForecastOrderEntry.getValue()) {
                            forecastOrderExportRequest.setErrorMessage("已配置每日库存分解限量，提报量不能大于每日库存分解数量");
                            /*forecastOrderExportRequest.setErrorMessage("存在无价格的商品");*/
                        }
                        it.setErrorMessage("已配置每日库存分解限量，提报量不能大于每日库存分解数量");
                        createFlag = false;
                        break;
                    }
                }
            }

            //加上对于价格为正数的判断
            if (CollectionUtils.isNotEmpty(forecastOrderLine) && forecastOrderLine.get(0).getUnitPrice() != null && forecastOrderLine.get(0).getUnitPrice() >= 0) {
                build.setUnitPrice(forecastOrderLine.get(0).getUnitPrice());
                if (Objects.nonNull(forecastOrderLine.get(0).getUnitPrice())) {
                    build.setTotalFee(forecastOrderLine.get(0).getUnitPrice() * Integer.parseInt(build.getQuantity()));
                }
            } else {
//                for (ForecastOrderExportRequest forecastOrderExportRequest : mainForecastOrderEntry.getValue()) {
//                    forecastOrderExportRequest.setErrorMessage("存在异常价格的商品");
//                    /*forecastOrderExportRequest.setErrorMessage("存在无价格的商品");*/
//                }
                it.setErrorMessage(scItemSDO.getOuterId() + "商品获取价格失败");
                createFlag = false;
                continue;
            }

            forecastOrderLineSDOS.add(build);
        }

        //2022.10.24 价格需要全部遍历报错原因 有报错提示同主单下其他行有错误
        if (!createFlag){
            for (ForecastOrderExportRequest forecastOrderExportRequest : forecastOrderExportRequests) {
                if (StringUtils.isBlank(forecastOrderExportRequest.getErrorMessage())){
                    forecastOrderExportRequest.setErrorMessage("同主单的其他销售单行报错");
                }
            }
        }

        if (createFlag) {
            String save = forecastOrderWriteRepository.save(sdo);
            sdo.setId(save);
            LogUtils.printOperateLog(sdo, ForecastOrderLogEnum.CREATE.getForecastOrderLogValue(), "创建预报订单", loginUser);
            List<ForecastOrderLineSDO> forecastOrderLineSDOList = sdo.getForecastOrderLineSDOList();
            for (ForecastOrderLineSDO forecastOrderLineSDO : forecastOrderLineSDOList) {
                forecastOrderLineSDO.setMainOrderId(save);
                forecastOrderLineWriteRepository.save(forecastOrderLineSDO);
            }
            //创建完成主单子单，进行订单提交
            try {
                SubmitForecastRequest submitForecastRequest = new SubmitForecastRequest();
                com.epoch.app.crforecastsales.model.dto.ApiContext apiContext = new com.epoch.app.crforecastsales.model.dto.ApiContext();
                apiContext.setEmployeeId(loginUser.getEmpId());
                apiContext.setEmployeeName(loginUser.getRealName());
                submitForecastRequest.setApiContext(apiContext);
                List<ForecastOrderSDO> forecastOrderSDOList = Lists.newArrayList(ForecastOrderSDO.builder().id(save).build());
                submitForecastRequest.setForecastOrderSDOList(forecastOrderSDOList);
                submitForecast(submitForecastRequest);
            } catch (Exception e) {
                log.error("导入预报订单提交失败,订单状态为待提交", e);
            }
        }
    }

    private Map<String, Object> queryDailyInv(ForecastOrderSDO sdo, ForecastOrderLineSDO build) {
        HashMap<String, Object> stringObjectHashMap = new HashMap<>();

        String organizationCode = sdo.getOrganizationCode();
        String channelCode = sdo.getChannelCode();
        String departmentCode = sdo.getDepartmentCode();
        String salesmanCode = sdo.getSalesmanCode();
        String wareHouseCode = sdo.getWareHouseCode();

        QueryAllotRequest queryAllotRequest = new QueryAllotRequest();
        queryAllotRequest.setOrganizationCode(organizationCode);
        queryAllotRequest.setChannelCode(channelCode);
        queryAllotRequest.setDepartmentCode(departmentCode);
        queryAllotRequest.setSalesmanCode(salesmanCode);
        queryAllotRequest.setWarehouseCode(wareHouseCode);
        queryAllotRequest.setScItemId(build.getScItemId());
        Result<QueryAllotResponse> result = inventoryAllotQueryService.queryAllot(queryAllotRequest);
        stringObjectHashMap.put("limitSwitch", false);
        if (Objects.nonNull(result) && Objects.nonNull(result.getResult())) {
            stringObjectHashMap.put("limitSwitch", result.getResult().getMainLimitSwitch());
            stringObjectHashMap.put("dailyInventory", result.getResult().getRemainingQuantity());
        }
        return stringObjectHashMap;
    }

    private List<SubOrderInfo> queryOrderLinePrice(ForecastOrderSDO sdo, ForecastOrderLineSDO build) {
        QueryGoodsDetailRequest queryGoodsDetailRequest = new QueryGoodsDetailRequest();
        ForecastOrderSDO tmpSdo = new ForecastOrderSDO();
        BeanUtils.copyProperties(sdo, tmpSdo);
        List<ForecastOrderLineSDO> tmpForecastOrderLineSDOS = new ArrayList<>();
        tmpSdo.setForecastOrderLineSDOList(tmpForecastOrderLineSDOS);
        tmpForecastOrderLineSDOS.add(build);
        String s1 = JSONObject.toJSONString(tmpSdo);
        MainOrderInfo mainOrderInfo = JSONObject.parseObject(s1, MainOrderInfo.class);
        queryGoodsDetailRequest.setForecastOrderSDO(mainOrderInfo);
        List<SubOrderInfo> forecastOrderLine = priceQueryUtils.queryGoodsDetail(queryGoodsDetailRequest);
        return forecastOrderLine;
    }

    private Map<String, String> batchQueryTransportMode(Set<String> transportModeCodeSet) {
        Map<String, String> transportModeCodeMap = Maps.newHashMap();
        for (String transportModeCode : transportModeCodeSet) {
            QueryDictionaryRequest queryDictionaryRequest = new QueryDictionaryRequest();
            queryDictionaryRequest.setDictCode("shipMethod");
            queryDictionaryRequest.setValueCode(transportModeCode);
            Result<String> stringResult = dictionaryQueryService.queryValueNameByCode(queryDictionaryRequest);
            if (stringResult != null && StringUtils.isNotBlank(stringResult.getResult())) {
                transportModeCodeMap.put(transportModeCode, stringResult.getResult());
            }
        }

        return transportModeCodeMap;
    }

    /**
     * 获取 登录人有权限的发货仓  和 导入发货仓 交集
     *
     * @param wareHouseCodeSet
     * @return
     */
    private Map<String, List<WarehouseInfo>> batchQueryWareHouse(Set<String> wareHouseCodeSet) {
        Map<String, List<WarehouseInfo>> warehouseMap = Maps.newHashMap();

        QueryCargoZoneListWithAccessRequest cargoZoneListRequest =
                QueryCargoZoneListWithAccessRequest.builder()
                        .model(3)
                        .status(1)
                        .typeList(Stream.of(3, 4,6).collect(Collectors.toList()))
                        .build();
        // 获取登陆人 仓库权限
        QueryCargoZoneListWithAccessResponse searchCargoZoneListForPageResponse = bcOrderService.queryCargoZoneListWithAccess(cargoZoneListRequest);
        if (ObjectUtils.isEmpty(searchCargoZoneListForPageResponse)) {
            return warehouseMap;
        }
        List<WarehouseInfo> result = searchCargoZoneListForPageResponse.getResult();
        if (CollectionUtils.isEmpty(result)) {
            return warehouseMap;
        }
        warehouseMap = result.stream()
                .filter(warehouseInfo -> wareHouseCodeSet.contains(warehouseInfo.getCode()))
                .collect(Collectors.groupingBy(WarehouseInfo::getCode));


//        for (String wareHouseCode : wareHouseCodeSet) {
//            WmsQueryWarehouseZoneListRequest byIdRequest = new WmsQueryWarehouseZoneListRequest();
//            byIdRequest.setCode(wareHouseCode);
//            WmsQueryWarehouseZoneListResponse warehouseInfoResult = unifiedInventoryService.wmsQueryWarehouseZoneList(byIdRequest);
//            if (warehouseInfoResult != null && warehouseInfoResult.getResult() != null) {
//                warehouseMap.put(wareHouseCode, warehouseInfoResult.getResult());
//            }
//        }
        return warehouseMap;
    }

    private Map<String, List<ScItemUnit>> batchQuerySaleUnitMap(Set<String> saleUnitSet) {
        Map<String, List<ScItemUnit>> receiveAddressCodeMap = Maps.newHashMap();
        for (String saleUnit : saleUnitSet) {
            ScItemUnitLoadListRequest scItemUnitLoadListRequest = ScItemUnitLoadListRequest
                    .newScItemUnitLoadListRequestBuilder().code(saleUnit).build();
            Result<List<ScItemUnit>> listResult1 = scItemUnitService.loadScItemUnitList(scItemUnitLoadListRequest);
            receiveAddressCodeMap.put(saleUnit, listResult1.getResult());
        }

        return receiveAddressCodeMap;
    }

    /**
     * 获取 登录人有权限的收货地址  和 导入收货地址 交集
     *
     * @param receiveAddressCodeSet
     * @param employeeGetCurrentLoginResponse
     * @return
     */
    private Map<String, List<CustomerAddressSDO>> batchQueryReceiveAddressMap
    (Set<String> receiveAddressCodeSet, EmployeeGetCurrentLoginResponse employeeGetCurrentLoginResponse) {
        Map<String, List<CustomerAddressSDO>> receiveAddressCodeMap = Maps.newHashMap();

        // 获取 登录人 拥有权限的 收货地址
        CustomerAddressBatchRequest addressBatchRequest = CustomerAddressBatchRequest.builder().addressCodes(new ArrayList<>(receiveAddressCodeSet)).build();
        addressBatchRequest.setStatus(1);

        String relatedOrganizationId = employeeGetCurrentLoginResponse.getRelatedOrganizationId();
        switch (employeeGetCurrentLoginResponse.getRelatedOrganizationType()) {
            case "103":
                // 分子公司
                addressBatchRequest.setOrgBussinessUnitCode(relatedOrganizationId);
                break;
            case "104":
                // 销售组织
                addressBatchRequest.setOrgSaleOrganizationCode(relatedOrganizationId);
                break;
            case "105":
                // 销售渠道
                addressBatchRequest.setOrgSaleChannelCode(relatedOrganizationId);
                break;
            case "106":
                // 销售部门
                addressBatchRequest.setOrgSaleDepartmentCode(relatedOrganizationId);
                break;
        }
        //1为启用状态 0禁用状态  -1非业务状态
        addressBatchRequest.setStatus(1);
        Result<List<CustomerAddressSDO>> listResult = customerAddressQueryService.batchQueryCustomerAddress(addressBatchRequest);
        List<CustomerAddressSDO> result = CollectionUtils.isEmpty(listResult.getResult()) ? new ArrayList<>() : listResult.getResult();
        receiveAddressCodeMap = result.stream()
                .filter(customerAddressSDO -> receiveAddressCodeSet.contains(customerAddressSDO.getAddressCode()))
                .collect(Collectors.groupingBy(CustomerAddressSDO::getAddressCode));


//        for (String receiveAddressCode : receiveAddressCodeSet) {
//            QueryAddressRequest queryAddressRequest = new QueryAddressRequest();
//            queryAddressRequest.setAddressCode(receiveAddressCode);
//            Result<List<CustomerAddressSDO>> customerAddress = customerAddressQueryService.pageQueryCustomerAddress(queryAddressRequest);
//            if (customerAddress != null && customerAddress.getResult() != null) {
//                receiveAddressCodeMap.put(receiveAddressCode, customerAddress.getResult());
//            }
//        }


        return receiveAddressCodeMap;
    }

    private Map<String, List<ScItemSDO>> batchQueryItem(Set<String> scItemCodeSet) {
        // es降级开关 若开关开启，需要走db降级查询 开关未开启，走原有逻辑
        GetEsDegradeValueResponse valueResponse = esDegradeService.getEsDegradeValue();
        if (Objects.nonNull(valueResponse) && valueResponse.getResult()) { //DB
            SearchScItemByDBWhenDegradedRequest searchScItemByDBWhenDegradedRequest = new SearchScItemByDBWhenDegradedRequest();
            SearchReqDTO searchReqDTO = new SearchReqDTO();
            List<String> list = Lists.newArrayList(scItemCodeSet);
            searchReqDTO.setOuterIdList(list);
            searchScItemByDBWhenDegradedRequest.setSearchReqDTO(searchReqDTO);
            searchScItemByDBWhenDegradedRequest.setPageNum(1);
            searchScItemByDBWhenDegradedRequest.setPageSize(list.size());
            Result<List<ScItemSDO>> listResult = baseDataService.searchScItemByDBWhenDegraded(searchScItemByDBWhenDegradedRequest);
            if (listResult != null && listResult.getResult() != null) {
                return listResult.getResult().stream().collect(Collectors.groupingBy(ScItemSDO::getOuterId));
            }
        } else { // es
            SearchScItemRequest searchScItemRequest = new SearchScItemRequest();
            SearchReqDTO searchReqDTO = new SearchReqDTO();
            List<String> list = Lists.newArrayList(scItemCodeSet);
            searchReqDTO.setOuterIdList(list);
            searchReqDTO.setBusinessType("11");//业态常温
            searchReqDTO.setType(0);//非组合货品
            searchScItemRequest.setSearchReqDTO(searchReqDTO);
            searchScItemRequest.setPageNum(1);
            searchScItemRequest.setPageSize(list.size());
            Result<List<ScItemSDO>> listResult = baseDataService.searchScItem(searchScItemRequest);
            if (listResult != null && listResult.getResult() != null) {
                return listResult.getResult().stream().collect(Collectors.groupingBy(ScItemSDO::getOuterId));
            }
        }

        return new HashMap<>();
    }

    private List<ScItemSDO> batchQueryItemsAllStatus(Set<String> scItemCodeSet) {
        // es降级开关 若开关开启，需要走db降级查询 开关未开启，走原有逻辑
        GetEsDegradeValueResponse valueResponse = esDegradeService.getEsDegradeValue();
        if (Objects.nonNull(valueResponse) && valueResponse.getResult()) { //DB
            SearchScItemByDBWhenDegradedRequest searchScItemByDBWhenDegradedRequest = new SearchScItemByDBWhenDegradedRequest();
            SearchReqDTO searchReqDTO = new SearchReqDTO();
            List<String> list = Lists.newArrayList(scItemCodeSet);
            searchReqDTO.setOuterIdList(list);
            searchReqDTO.setStatusList(Lists.newArrayList(1,-1));
            searchScItemByDBWhenDegradedRequest.setSearchReqDTO(searchReqDTO);
            searchScItemByDBWhenDegradedRequest.setPageNum(1);
            searchScItemByDBWhenDegradedRequest.setPageSize(list.size());
            Result<List<ScItemSDO>> listResult = baseDataService.searchScItemByDBWhenDegraded(searchScItemByDBWhenDegradedRequest);
            if (listResult != null && listResult.getResult() != null) {
                return listResult.getResult();
            }
        } else { // es
            SearchScItemRequest searchScItemRequest = new SearchScItemRequest();
            SearchReqDTO searchReqDTO = new SearchReqDTO();
            List<String> list = Lists.newArrayList(scItemCodeSet);
            searchReqDTO.setOuterIdList(list);
            searchReqDTO.setBusinessType("11");//业态常温
            searchReqDTO.setType(0);//非组合货品
            searchReqDTO.setStatusList(Lists.newArrayList(1,-1));
            searchScItemRequest.setSearchReqDTO(searchReqDTO);
            searchScItemRequest.setPageNum(1);
            searchScItemRequest.setPageSize(list.size());
            Result<List<ScItemSDO>> listResult = baseDataService.searchScItem(searchScItemRequest);
            if (listResult != null && listResult.getResult() != null) {
                return listResult.getResult();
            }
        }

        return new ArrayList<>();
    }

    /**
     * 获取 登录人有权限的业务渠道  和 导入业务渠道 交集
     *
     * @param channelCodeSet
     * @param ids
     * @return
     */
    private Map<String, OrganizationChannelRelationSDO> batchQueryChannelMap(Set<String> channelCodeSet, List<String> ids) {
        Map<String, OrganizationChannelRelationSDO> channelMap = Maps.newHashMap();

        // 获取 登陆人 拥有权限的 渠道
        GetOrgChannelRelationByOrgId2Request request = GetOrgChannelRelationByOrgId2Request.builder().ids(ids).build();
        Result<List<OrganizationChannelRelationSDO>> orgChannelRelationByOrgId2 = crPlatformEnhanceService.getOrgChannelRelationByOrgId2(request);
        if (ObjectUtils.isEmpty(orgChannelRelationByOrgId2)) {
            return channelMap;
        }
        List<OrganizationChannelRelationSDO> result = orgChannelRelationByOrgId2.getResult();
        if (CollectionUtils.isEmpty(result)) {
            return channelMap;
        }

//        for (String channel : channelCodeSet) {
//            QueryChannelRequest baselineBatchQueryChannelsRequest = new QueryChannelRequest();
//            baselineBatchQueryChannelsRequest.setOutCode(channel);
//            //调用查询渠道信息
//            Result<ChannelResponse> result = channelService.queryChannelDetail(baselineBatchQueryChannelsRequest);
//            if (result != null && result.getResult() != null) {
//                channelMap.put(channel, result.getResult());
//            }
//        }
        channelMap = result.stream()
                .filter(organizationChannelRelationSDO -> channelCodeSet.contains(organizationChannelRelationSDO.getCode()))
                .collect(Collectors.toMap(OrganizationChannelRelationSDO::getOutCode, o -> o, (v1, v2) -> v1));
        return channelMap;
    }

    private Map<String, ScItemGroupResponse> batchQueryProductGroup(Set<String> productGroupCodeSet) {
        Map<String, ScItemGroupResponse> productGroupMap = Maps.newHashMap();
        for (String productGroup : productGroupCodeSet) {
            QueryScItemGroupRequest request = new QueryScItemGroupRequest();
            request.setCode(productGroup);
            Result<ScItemGroupResponse> result = scItemGroupQueryService.getScItemGroup(request);
            if (result != null && result.getResult() != null && StringUtils.isNotBlank(result.getResult().getCode())) {
                productGroupMap.put(productGroup, result.getResult());
            }
        }
        return productGroupMap;
    }

    /**
     * 获取 登录人有权限的销售组织  和 导入销售组织 交集
     *
     * @param organizationCodeSet
     * @return
     */
    private Map<String, List<OrganizationSDO>> batchQeuryOrgMap(Set<String> organizationCodeSet) {
        // 权限控制在这里加
        List<OrganizationSDO> loginOrganizationCode = getLoginOrganizationCode(OrganizationTypeEnum.SALES_ORGANIZATION.getCode());
        Map<String, List<OrganizationSDO>> organizationMap =
                loginOrganizationCode.stream()
                        .filter(organizationSDO -> organizationCodeSet.contains(organizationSDO.getCode()))
                        .collect(Collectors.groupingBy(OrganizationSDO::getCode));


        return organizationMap;
    }

    @Override
    @FacadeInvoker // TBD 消息是否可以重投？
    public Result<Void> forecastOrderStatusBack(ForecastOrderStatusBackRequest msg) {
        TradeMessageSDO tradeMessageSDO = JSONObject.parseObject(msg.getMessage(), TradeMessageSDO.class);

        if (CollectionUtils.isEmpty(tradeMessageSDO.getAffectLineIds())) {
            throw new FunctionException("OTS-04-001-00-15-029");
        }
        if (CollectionUtils.isEmpty(tradeMessageSDO.getOrderSDO().getOrderLineSDOS())) {
            throw new FunctionException("OTS-04-001-00-15-030");
        }
        // 受影响的销售子单
        List<OrderLineSDO> sdoList = tradeMessageSDO.getOrderSDO().getOrderLineSDOS()
                .stream()
                .filter(orderLine ->
                        tradeMessageSDO.getAffectLineIds().contains(orderLine.getId()))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(sdoList)) {
            return Result.success(null);
        }
        //这里销售子单 与 预报子单是1比1
        // 销售子单map
        Map<String, OrderLineSDO> orderLineMap = Maps.newHashMap();
        // 这里只取主品子单进行回退，如果是赠品等场景的子单不需要回退，像特价场景按正常订单处理
        sdoList.forEach(orderLineSDO -> {
            if (StringUtils.endsWith(orderLineSDO.getSerialNumber(), "0")) {
                orderLineMap.put(orderLineSDO.getFrontOrderLineId(), orderLineSDO);
            }
        });

        // 销售子单对应的预报子单
        List<String> idList = Lists.newArrayList(orderLineMap.keySet());
        PageResult<List<ForecastOrderLineSDO>> result = forecastOrderLineQueryRepository.batchLoadList(idList);
        if (CollectionUtils.isEmpty(result.getContent())) {
            return Result.success(null);
        }
        List<ForecastOrderLineSDO> forecastOrderLines = Lists.newArrayList();
        Map<String, OrderLineSDO> finalOrderLineMap = orderLineMap;
        result.getContent().forEach(forecastOrderLine -> {
            String id = String.valueOf(forecastOrderLine.getId());
            OrderLineSDO orderLineSDO = finalOrderLineMap.get(id);
            //销售子单货品数量
            int totalScItemAmount = orderLineSDO.getScItemSDO().getQuantity();
            // 预报子单累计回复数量
            Integer actualTotalReplyAmount = forecastOrderLine.getActualTotalReplyAmount();
            if (actualTotalReplyAmount > totalScItemAmount) {
                forecastOrderLine.setActualTotalReplyAmount(actualTotalReplyAmount - totalScItemAmount);
                forecastOrderLine.setStatus(ForecastStatusEnum.PARTIAL_REPLY.getNumValue());
            } else {
                forecastOrderLine.setActualTotalReplyAmount(0);
                forecastOrderLine.setStatus(ForecastStatusEnum.WAITING_FOR_REPLY.getNumValue());
            }
            forecastOrderLines.add(forecastOrderLine);
        });
        if (CollectionUtils.isEmpty(forecastOrderLines)) {
            return Result.success(null);
        }
        ForecastOrderSDO detail = forecastOrderQueryRepository.queyrDetail(tradeMessageSDO.getOrderSDO().getFrontOrderId());
        // 更新主单、子单状态
        forecastOrderWriteRepository.updateForecastStatus(forecastOrderLines, detail);
        return Result.success(null);
    }

    public int totalScItemAmount(List<OrderLineSDO> orderLineList) {
        int totalAmount = 0;
        for (OrderLineSDO sdo : orderLineList) {
            Integer integer = Optional.ofNullable(sdo.getScItemSDO()).map(com.epoch.app.crb2btradecenter.sdo.ScItemSDO::getQuantity).orElse(0);
            totalAmount = totalAmount + integer;
        }
        return totalAmount;
    }

    /**
     * 获取 登录人 所属销售组织code
     *
     * @param type
     * @return
     */
    private List<OrganizationSDO> getLoginOrganizationCode(Integer type) {
        GetLoginEmployOrganizationPermissionsRequest request = GetLoginEmployOrganizationPermissionsRequest.builder().type(type).build();
        Result<List<OrganizationSDO>> loginEmployOrganizationPermissions = crPlatformEnhanceService.getLoginEmployOrganizationPermissions(request);
        if (ObjectUtils.isEmpty(loginEmployOrganizationPermissions)) {
            return new ArrayList<>();
        }
        List<OrganizationSDO> result = loginEmployOrganizationPermissions.getResult();
        if (CollectionUtils.isEmpty(result)) {
            return new ArrayList<>();
        }
        return result;
    }

    //补货订单查询活动信息
    private Map<String, List<ActivityInfoResponse>> activityQueryCode(List<ForecastOrderExportRequest> forecastOrderExportRequests,
                                                                      EmployeeGetCurrentLoginResponse employeeGetCurrentLoginResponse) {
        if (CollectionUtils.isEmpty(forecastOrderExportRequests)) {
            return new HashMap<>();
        }
        // 只能根据逐个货品进行活动查询，多个货品的查询结果，无法匹配对应的货品 使用在进行补货活动，其他货品查询活动咨询峥嵘
        Map<String, List<ActivityInfoResponse>> stringListMap = new HashMap<>();
        QueryActivityRequest queryActivityRequest = new QueryActivityRequest();
        List<ActivityInfoRequest> activityInfoRequestList = Lists.newArrayList();
        for (ForecastOrderExportRequest forecastOrder : forecastOrderExportRequests) {
            Date customerExpectTDate = forecastOrder.getCustomerExpectTDate();
            //默认当天
            if (Objects.isNull(customerExpectTDate) || Objects.equals(customerExpectTDate, "")) {
                customerExpectTDate = new Date();
            }
            String s = UUIDUtil.newWithoutMinus();

            PageQueryAddressListByPrincipalRequest pageQueryAddressListByPrincipalRequest = new PageQueryAddressListByPrincipalRequest();
            pageQueryAddressListByPrincipalRequest.setAddressCode(forecastOrder.getReceiveAddressCode());
            pageQueryAddressListByPrincipalRequest.setStatus(1);
            PageQueryAddressListByPrincipalResponse listByPrincipalResponse = crPlatformEnhanceService.pageQueryAddressListByPrincipal(pageQueryAddressListByPrincipalRequest);
//            Result<CustomerAddressSDO> customerAddressSDOResult = customerAddressQueryService.queryCustomerAddressByShipAddressId(request);
            String clientId = "";
            if (Objects.nonNull(listByPrincipalResponse)&&listByPrincipalResponse.getSuccess() && CollectionUtils.isNotEmpty(listByPrincipalResponse.getResult())) {
                JSONObject customerAddress = JSONObject.parseObject(JSONObject.toJSONString(listByPrincipalResponse.getResult().get(0)));
                clientId = customerAddress.getString("customerCode");
            }

            if (StringUtils.isBlank(clientId)){
                continue;
            }

            //导入逻辑变更 add by myw
            String key = forecastOrder.getOrderType() + forecastOrder.getOrganizationCode() + forecastOrder.getProductGroupCode() + forecastOrder.getChannelCode()
                    + forecastOrder.getReceiveAddressCode() + forecastOrder.getCustomerReferenceNo() + forecastOrder.getScItemId();

            ActivityInfoRequest build = ActivityInfoRequest.builder()
                    //获取客户ID
                    .clientId(clientId) //客户编码
                    .activityUseTime(customerExpectTDate)
                    .deliveryDate(customerExpectTDate)
                    .mainOrderId(key)
                    .subOrderId("subOrder_" + s)
                    .salesOrganization(forecastOrder.getOrganizationCode())
                    .businessChannel(forecastOrder.getChannelCode())
                    .shipAddressId(forecastOrder.getReceiveAddressCode()) //收货地址
                    .orderType(forecastOrder.getOrderType()).build();
            List<ActivityItemInfoRequest> itemList = Lists.newArrayList();
            ActivityItemInfoRequest activityItemInfoRequest = ActivityItemInfoRequest
                    .builder().itemId(forecastOrder.getScItemId())
                    .salesUnit(forecastOrder.getSaleUnit())
                    .itemQuantity(new BigDecimal(forecastOrder.getQuantity()).longValue()).build();
            itemList.add(activityItemInfoRequest);
            build.setItemList(itemList);
            activityInfoRequestList.add(build);
        }
        queryActivityRequest.setActivityInfoRequestList(activityInfoRequestList);
        if (CollectionUtils.isNotEmpty(activityInfoRequestList)){
            Result<ActivityResponse> activityResponseResult = activityQueryService.batchQueryCanUsingActivity(queryActivityRequest);
            stringListMap = Nullable.stream(activityResponseResult.getResult().getActivityInfoResponseList()).collect(Collectors.groupingBy(ActivityInfoResponse::getMainOrderId));
        }
        return stringListMap;
    }

    @Override
    @FacadeInvoker
    public Result<List<ForecastOrderOutResponse>> batchCreateForecastOrderForOut(BatchCreateForecastOrderForOutRequest batchCreateForecastOrderForOutRequest) {
        if (Objects.isNull(batchCreateForecastOrderForOutRequest) || CollectionUtils.isEmpty(batchCreateForecastOrderForOutRequest.getForecastOrderDTOS())) {
            throw new FunctionException("预报订单创建参数数据不能为空");
        }
        List<ForecastOrderOutResponse> result = new ArrayList<>();

        for (ForecastOrderDTO forecastOrderDTO : batchCreateForecastOrderForOutRequest.getForecastOrderDTOS()) {
            ForecastOrderOutResponse response = new ForecastOrderOutResponse();
            boolean createFlag = Boolean.TRUE;
            List<ForecastOrderDetailDTO> orderLineToQueryActive = Lists.newArrayList();
            StringBuffer message = new StringBuffer();
            // 必填校验
            response.setReferenceNo(forecastOrderDTO.getReferenceNo());
            validMainOrder(forecastOrderDTO, message);
            if (StringUtils.isNotBlank(message.toString())) {
                response.setMessage(message.toString());
                response.setSuccess(Boolean.FALSE);
                result.add(response);
                continue;
            }
            String organizationCode = forecastOrderDTO.getOrganizationCode();
            String channelCode = forecastOrderDTO.getChannelCode();
            String customerCode = forecastOrderDTO.getCustomerCode();
            String receiveAddressCode = forecastOrderDTO.getReceiveAddressCode();
            String transportModeCode = forecastOrderDTO.getTransportModeCode();
            String productGroupCode = forecastOrderDTO.getProductGroupCode();
            String createReason = forecastOrderDTO.getCreateReason();
            String factoryCode = forecastOrderDTO.getFactoryCode();
            String inventoryCode = forecastOrderDTO.getInventoryCode();
            String expectDeliveryDate = forecastOrderDTO.getExpectDeliveryDate();

            ForecastOrderSDO forecastOrderSDO = new ForecastOrderSDO();
            forecastOrderSDO.setBizCode(batchCreateForecastOrderForOutRequest.getBizCode());
            forecastOrderSDO.setBusinessCode(batchCreateForecastOrderForOutRequest.getBizCode());
            forecastOrderSDO.setReceiveAddressCode(receiveAddressCode);
            forecastOrderSDO.setOrderType(forecastOrderDTO.getOrderType());
            forecastOrderSDO.setRemark(forecastOrderDTO.getRemark());
            forecastOrderSDO.setCustomerReferenceNo(forecastOrderDTO.getReferenceNo());
            forecastOrderSDO.setCreateReason(createReason);
            forecastOrderSDO.setChannelCode(channelCode);

            //客户期望日期
            if (StringUtils.isNotBlank(expectDeliveryDate)){
                SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd");
                try {
                    Date expectDate = simpleDateFormat.parse(expectDeliveryDate);
                    forecastOrderSDO.setCustomerExpectTDate(expectDate);
                } catch (ParseException e) {
                    log.error("parse expectDeliveryDate error", e);
                }
            }else {
                forecastOrderSDO.setCustomerExpectTDate(new Date());
            }

            //创建人信息
            forecastOrderSDO.setCreatorId(forecastOrderDTO.getCreateId());
            forecastOrderSDO.setCreatorName(forecastOrderDTO.getCreateName());
            forecastOrderSDO.setModifierId(forecastOrderDTO.getCreateId());
            forecastOrderSDO.setModifierName(forecastOrderDTO.getCreateName());

            if (StringUtils.isNotBlank(productGroupCode) && null != ItemGroupEnum.of(productGroupCode)) {
                forecastOrderSDO.setProductGroupCode(productGroupCode);
                forecastOrderSDO.setProductGroupName(ItemGroupEnum.of(productGroupCode).getValue());
            }
            if (StringUtils.isNotBlank(transportModeCode) && null != TransportModeEnum.of(transportModeCode)) {
                forecastOrderSDO.setTransportModeCode(transportModeCode);
                forecastOrderSDO.setTransportModeName(TransportModeEnum.of(transportModeCode).getDesc());
            }
            forecastOrderSDO.setTransportModeCode(forecastOrderDTO.getTransportModeCode());
            //业务单号
            String nextStringSequence = customSequenceAccessor.getNextStringSequence("cr_forecast_sales", "forecastOrderId");
            forecastOrderSDO.setOrderBizId(nextStringSequence);
            //仓库信息
            SpecQueryWarehouseRequest cargoRequest = new SpecQueryWarehouseRequest();
            cargoRequest.setFactoryCode(factoryCode);
            cargoRequest.setInventoryCode(inventoryCode);
            cargoRequest.setModel(3);
            //销售单元仓
            cargoRequest.setTypeList(Lists.newArrayList(3, 6));

            Result<List<WarehouseInfo>> cargoResponse = bcOrderService.specQueryWarehouse(cargoRequest);
//            SearchCargoZoneListForPageResponse cargoResponse = unifiedInventoryService.searchCargoZoneListForPage(cargoRequest);
            if (Objects.isNull(cargoResponse) || CollectionUtils.isEmpty(cargoResponse.getResult())) {
                message.append("发货仓库不存在!工厂编码:").append(factoryCode).append("库存地点编码:").append(inventoryCode);
                response.setMessage(message.toString());
                response.setSuccess(Boolean.FALSE);
                result.add(response);
                continue;
            }
            WarehouseInfo warehouseInfo = cargoResponse.getResult().get(0);
            forecastOrderSDO.setWareHouseCode(warehouseInfo.getId());
            forecastOrderSDO.setWareHouseName(warehouseInfo.getName());

            //销售组织
            BaselineGetOrganizationByOutCodes2Request baselineGetOrganizationByOutCodes2Request = new BaselineGetOrganizationByOutCodes2Request();
            baselineGetOrganizationByOutCodes2Request.setOutCodes(Lists.newArrayList(organizationCode));
            BaselineGetOrganizationByOutCodes2Response organization = baseDataService.baselineGetOrganizationByOutCodes2(baselineGetOrganizationByOutCodes2Request);
            if (Objects.isNull(organization) || CollectionUtils.isEmpty(organization.getResult())) {
                message.append("销售组织不存在!销售组织编码:").append(organizationCode);
                response.setMessage(message.toString());
                response.setSuccess(Boolean.FALSE);
                result.add(response);
                continue;
            }
            com.epoch.app.bcorder.model.dto.OrganizationSDO organizationSDO = organization.getResult().get(0);
            forecastOrderSDO.setOrganizationCode(organizationSDO.getId());
            forecastOrderSDO.setOrganizationName(organizationSDO.getName());

            //客户送达方
            PageQueryAddressListRequest pageQueryCustomerAddressDataRequest = new PageQueryAddressListRequest();
            pageQueryCustomerAddressDataRequest.setAddressCode(receiveAddressCode);
            pageQueryCustomerAddressDataRequest.setCustomerCode(customerCode);
            //pageQueryCustomerAddressDataRequest.setOrgSaleOrganizationCode(organizationSDO.getId());
            pageQueryCustomerAddressDataRequest.setStatus(1);
            PageQueryAddressListResponse addressDataResponse = crPlatformEnhanceService.pageQueryAddressList(pageQueryCustomerAddressDataRequest);
            if (Objects.isNull(addressDataResponse) || CollectionUtils.isEmpty(addressDataResponse.getResult())) {
                message.append("客户送达方不存在!送达方编码:").append(receiveAddressCode).append("客户编码:").append(customerCode);
                response.setMessage(message.toString());
                response.setSuccess(Boolean.FALSE);
                result.add(response);
                continue;
            }

            CustomerAddressSDO customerAddress = JSONObject.parseObject(JSONObject.toJSONString(addressDataResponse.getResult().get(0)), CustomerAddressSDO.class);
            enrichCustomerAddressInfo(forecastOrderSDO, customerAddress);

            forecastOrderSDO.setStatus(ForecastStatusEnum.DRAFT.getNumValue());
            Map<String,String> mainFeature = new HashMap<>();
            mainFeature.put(ForecastConstants.OS, "teTong");
            forecastOrderSDO.setFeatures(mainFeature);
            //外部货品ID集合
            Set<String> scItemCodeSet = Sets.newHashSet();

            for (ForecastOrderDetailDTO forecastOrderDetailDTO : forecastOrderDTO.getForecastOrderDetailDTOS()) {
                validSubForecastOrder(forecastOrderDTO, orderLineToQueryActive, message, forecastOrderDetailDTO, scItemCodeSet);

            }
            Map<String, List<ActivityInfoResponse>> activityMap = activityQueryCodeSpec(forecastOrderDTO, orderLineToQueryActive);
            // 货品
            Map<String, List<ScItemSDO>> scItemMap = batchQueryItem(scItemCodeSet);

            List<ForecastOrderLineSDO> forecastOrderLineSDOS = new ArrayList<>();
            //子单行号
            int i = 1;
            //预报子单信息组装
            for (ForecastOrderDetailDTO forecastOrderDetailDTO : forecastOrderDTO.getForecastOrderDetailDTOS()) {
                //补货活动校验
                validSubForecastOrderActivity(forecastOrderDTO, message, activityMap, forecastOrderDetailDTO);


                Map<String,String> map = new HashMap<>();
                map.put(ForecastConstants.ACTIVITY_NUMBER, forecastOrderDetailDTO.getActivityProjectCodeproject());
                map.put(ForecastConstants.OS, "teTong");
//                map.put(ForecastConstants.FORECAST_ORDER_IMPORT_INDEX, Optional.ofNullable(it.getFeatures()).orElse(Maps.newHashMap()).getOrDefault(ForecastConstants.FORECAST_ORDER_IMPORT_INDEX, ""));
                ForecastOrderLineSDO build = ForecastOrderLineSDO.builder()
                        .scItemId(forecastOrderDetailDTO.getScItemId())
                        .quantity(String.valueOf(forecastOrderDetailDTO.getQuantity()))
                        .saleUnit(forecastOrderDetailDTO.getSaleUnit())
                        .serialNumber(String.valueOf(i * 10))
                        .status(ForecastStatusEnum.DRAFT.getNumValue())
                        .warehouseArea(forecastOrderSDO.getWareHouseCode())
                        .mainOrderBizId(forecastOrderSDO.getOrderBizId())
                        .detailRemark(forecastOrderDetailDTO.getDetailRemark())
                        .saleUnitCode(forecastOrderDetailDTO.getSaleUnit())
                        .activityCode(forecastOrderDetailDTO.getActivityCode())
                        .dealStatus(ForecastDealStatusSEO.WAITING_DEAL.getStatus())
                        .customerCode(forecastOrderSDO.getCustomerCode())
                        .customerName(forecastOrderSDO.getCustomerName())
                        .activityNumber(forecastOrderDetailDTO.getActivityProjectCodeproject())
                        .features(map).build();
                i++;
                //补货预报订单加活动信息  且匹配到活动信息
                String key = forecastOrderSDO.getCustomerReferenceNo() + forecastOrderDetailDTO.getScItemId();
                if (forecastOrderSDO.getOrderType().equals(SaleOrderTag.REPLENISH_FORECAST.getCode()) && CollectionUtils.isNotEmpty(activityMap.get(key))) {

                    List<ActivityInfoResponse> activityInfoResponses = activityMap.get(key);
                    List<ActivityInfoResponse> realActivityList = Nullable.stream(activityInfoResponses).filter(e ->
                            Objects.equals(e.getActivityId(), forecastOrderDetailDTO.getActivityCode())).collect(Collectors.toList());
                    ActivityInfoResponse activityInfoResponse = realActivityList.get(0);//补货活动匹配到的活动
                    Nullable.stream(activityInfoResponse.getActivityTermList()).forEach(active -> {
                        if (Objects.equals(active.getActivityTermId(), forecastOrderDetailDTO.getActivityProjectCodeproject())) {
                            build.setActivityCode(activityInfoResponse.getActivityId());
                            build.setActivityName(activityInfoResponse.getActivityNoteName());
                            build.setIntensityOfActivityDesc(active.getIntensityOfActivityDesc());
                            build.setActivityNumber(active.getActivityTermId());
                            build.setActivityVersion(active.getVersion());
                            build.setActivityRemainingFee(active.getActivityRemainingFee());
                            build.setActivityRemainingQuantity(active.getActivityRemainingQuantity());
                        }
                    });
                }
                if (!scItemMap.containsKey(build.getScItemId())){
                    message.append("存在异常商品!货品编码:").append(forecastOrderDetailDTO.getScItemId());
                    createFlag = false;
                    continue;
                }
                ScItemSDO scItemSDO = scItemMap.get(build.getScItemId()).get(0);
                build.setScItemOutCode(scItemSDO.getOuterId());
                build.setScItemTitle(scItemSDO.getTitle());
                build.setScItemId(scItemSDO.getScItemId());
                build.setGoodsCode(scItemSDO.getOuterId());
                Map<String, String> features = scItemSDO.getFeatures();

                if (MapUtils.isNotEmpty(features)) {
                    String unitName = features.get("unit");
                    String unitCode = features.get("unitName");
                    if (StringUtils.isNotBlank(unitName)) {
                        build.setInventoryUnit(unitName);
                    }
                    if (StringUtils.isNotBlank(unitCode)) {
                        build.setInventoryUnitCode(unitCode);
                    }
                    build.setCategoryCode(features.get("category"));
                    build.setCategoryDesc(features.get("categoryDesc"));
                    build.setCategoryChildCode(features.get("categoryChildCode"));
                    build.setCategoryChildDesc(features.get("categoryChildDesc"));
                }

                QuerySaleUnitRequest querySaleUnitRequest = QuerySaleUnitRequest.builder().scItemId(scItemSDO.getScItemId()).build();
                querySaleUnitRequest.setInventoryUnit(build.getInventoryUnit());
                querySaleUnitRequest.setInventoryUnitCode(build.getInventoryUnitCode());
                querySaleUnitRequest.setUnitConvert("1");
                Result<List<SelectCombox>> querySaleUnitList = forecastOrderLineQueryService.querySaleUnitList(querySaleUnitRequest);
                if (querySaleUnitList.isSuccess() && Objects.nonNull(querySaleUnitList.getResult())) {
                    List<SelectCombox> querySaleUnitListResult = querySaleUnitList.getResult();
                    Map<String, SelectCombox> unitMap = new HashMap<>();
                    Nullable.stream(querySaleUnitListResult).forEach(t -> unitMap.put(t.getValue(), t));
                    SelectCombox selected = unitMap.get(build.getSaleUnitCode());
                    if (selected != null) {
                        build.setSaleUnit(selected.getLabel());
                        build.setUnitConvert(selected.getExt());
                    }

                    SelectCombox inventoryMap = unitMap.get(build.getSaleUnitCode());
                    if (inventoryMap != null) {
                        build.setInventoryUnit(inventoryMap.getLabel());
                    }
                }

                List<SubOrderInfo> forecastOrderLine = queryOrderLinePrice(forecastOrderSDO, build);

                Map<String, Object> dailyInventory = queryDailyInv(forecastOrderSDO, build);
                if ((boolean) dailyInventory.getOrDefault("limitSwitch", false)) {
                    if (StringUtils.isNotBlank(String.valueOf(dailyInventory.get("dailyInventory")))) {
                        BigDecimal dailyInventory1 = new BigDecimal(String.valueOf(dailyInventory.get("dailyInventory"))).setScale(3, RoundingMode.DOWN);
                        BigDecimal bigDecimal = new BigDecimal(build.getQuantity()).setScale(3, RoundingMode.DOWN);
                        if (bigDecimal.compareTo(dailyInventory1) > 0) {
                            message.append("已配置每日库存分解限量，提报量不能大于每日库存分解数量!货品编码:"+forecastOrderDetailDTO.getScItemId());
                            createFlag = false;
                            continue;
                        }
                    }
                }

                //加上对于价格为正数的判断
                if (CollectionUtils.isNotEmpty(forecastOrderLine) && forecastOrderLine.get(0).getUnitPrice() != null && forecastOrderLine.get(0).getUnitPrice() >= 0) {
                    build.setUnitPrice(forecastOrderLine.get(0).getUnitPrice());
                    if (Objects.nonNull(forecastOrderLine.get(0).getUnitPrice())) {
                        build.setTotalFee(forecastOrderLine.get(0).getUnitPrice() * Integer.parseInt(build.getQuantity()));
                    }
                } else {
                    message.append("存在异常价格的商品!货品编码:"+forecastOrderDetailDTO.getScItemId());
                    createFlag = false;
                    continue;
                }
                forecastOrderLineSDOS.add(build);
            }

            if (createFlag) {
                String mainOrderId = forecastOrderWriteRepository.save(forecastOrderSDO);

                if (StringUtils.isBlank(mainOrderId)) {
                    message.append("创建预报单主单失败！");
                    response.setMessage(message.toString());
                    response.setSuccess(Boolean.FALSE);
                    result.add(response);
                    continue;
                }

                //批量报错预报子单
                for (ForecastOrderLineSDO forecastOrderLineSDO : forecastOrderLineSDOS) {
                    forecastOrderLineSDO.setMainOrderId(mainOrderId);
                    try {
                        String save = forecastOrderLineWriteRepository.save(forecastOrderLineSDO);
                        forecastOrderLineSDO.setId(Long.parseLong(save));
                    } catch (Exception e) {
                        message.append("创建预报单子单保存失败!货品编码:").append(forecastOrderLineSDO.getGoodsCode());
                        response.setForecastOrderBizNo(forecastOrderSDO.getOrderBizId());
                        response.setMessage(e.getMessage());
                        response.setSuccess(Boolean.FALSE);
                        result.add(response);
                    }
                }
                //创建完成主单子单，进行订单提交
                try {
                    SubmitForecastRequest submitForecastRequest = new SubmitForecastRequest();
                    com.epoch.app.crforecastsales.model.dto.ApiContext apiContext = new com.epoch.app.crforecastsales.model.dto.ApiContext();
                    apiContext.setEmployeeId(forecastOrderDTO.getCreateId());
                    apiContext.setEmployeeName(forecastOrderDTO.getCreateName());
                    submitForecastRequest.setApiContext(apiContext);
                    List<ForecastOrderSDO> forecastOrderSDOList = Lists.newArrayList(ForecastOrderSDO.builder().id(mainOrderId).build());
                    submitForecastRequest.setForecastOrderSDOList(forecastOrderSDOList);
                    Result<Boolean> submitResult = submitForecast(submitForecastRequest);
                    if (Objects.isNull(submitResult)){
                        response.setForecastOrderBizNo(forecastOrderSDO.getOrderBizId());
                        response.setMessage("预报订单提交失败,订单状态为待提交");
                        response.setSuccess(Boolean.FALSE);
                        result.add(response);
                        continue;
                    }
                    if (!submitResult.isSuccess()||!submitResult.getResult()){
                        response.setForecastOrderBizNo(forecastOrderSDO.getOrderBizId());
                        response.setMessage("预报订单提交失败,订单状态为待提交!失败原因:"+submitResult.getMessage());
                        response.setSuccess(Boolean.FALSE);
                        result.add(response);
                        continue;
                    }

                } catch (Exception e) {
                    response.setForecastOrderBizNo(forecastOrderSDO.getOrderBizId());
                    response.setMessage("预报订单提交失败,订单状态为待提交!失败原因:"+e.getMessage());
                    response.setSuccess(Boolean.FALSE);
                    result.add(response);
                    log.error("预报订单提交失败,订单状态为待提交", e);
                    continue;
                }
                //组装子单返回参数
                List<ForecastOrderDetailResponseDTO> forecastOrderDetailResponseDTOS = new ArrayList<>();
                castForecastDetailForSpec(forecastOrderLineSDOS,forecastOrderDetailResponseDTOS);
                response.setForecastOrderDetailResponseDTOS(forecastOrderDetailResponseDTOS);
                response.setForecastOrderBizNo(forecastOrderSDO.getOrderBizId());
                response.setSuccess(Boolean.TRUE);
                result.add(response);
            }else {
                response.setForecastOrderBizNo(forecastOrderSDO.getOrderBizId());
                response.setMessage("预报订单创建失败!失败原因:"+message);
                response.setSuccess(Boolean.FALSE);
                result.add(response);
            }


        }
        List<String> bizNos = Nullable.stream(result).map(ForecastOrderOutResponse::getForecastOrderBizNo).filter(StringUtils::isNotBlank).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(bizNos)){
            HashMap<String, Object> mqMessageMap = new HashMap<>();
            mqMessageMap.put("forecastOrderBizIds",bizNos);
            String message = JSON.toJSONString(mqMessageMap);
            Map<String, String> map = new HashMap<>();
            map.put("_CZ_KEY", BcOrderConstants.TENANT_ID());
            log.info("orderId = " + JSON.toJSONString(bizNos) + ", message = " + message + ",map = " + JSON.toJSONString(map) + " start");
            messageService.sendMessage("createSpecForecastQueue", "createSpecForecast_V2", "createSpecForecastTetong", bizNos.get(0), message, map);
        }

        return Result.success(result);
    }

    private void castForecastDetailForSpec(List<ForecastOrderLineSDO> forecastOrderLineSDOS, List<ForecastOrderDetailResponseDTO> forecastOrderDetailResponseDTOS) {
        for (ForecastOrderLineSDO forecastOrderLineSDO : forecastOrderLineSDOS) {
            ForecastOrderDetailResponseDTO detailResponseDTO = ForecastOrderDetailResponseDTO.builder()
                    .scItemId(forecastOrderLineSDO.getScItemOutCode())
                    .id(String.valueOf(forecastOrderLineSDO.getId()))
                    .quantity(Integer.parseInt(forecastOrderLineSDO.getQuantity()))
                    .saleUnit(forecastOrderLineSDO.getSaleUnitCode())
                    .detailRemark(forecastOrderLineSDO.getDetailRemark())
                    .activityCode(forecastOrderLineSDO.getActivityCode())
                    .activityProjectCodeproject(forecastOrderLineSDO.getActivityNumber())
                    .build();
            forecastOrderDetailResponseDTOS.add(detailResponseDTO);
        }

    }

    private void validSubForecastOrderActivity(ForecastOrderDTO forecastOrderDTO, StringBuffer message, Map<String, List<ActivityInfoResponse>> activityMap, ForecastOrderDetailDTO forecastOrderDetailDTO) {
        if (forecastOrderDTO.getOrderType().equals(SaleOrderTag.REPLENISH_FORECAST.getCode())) {
            String key = forecastOrderDTO.getReferenceNo() + forecastOrderDetailDTO.getScItemId();
            List<ActivityInfoResponse> activityInfoResponses1 = activityMap.get(key);
            List<String> collect = Nullable.stream(activityInfoResponses1).map(ActivityInfoResponse::getActivityId).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(activityInfoResponses1) || !collect.contains(StringUtils.trim(forecastOrderDetailDTO.getActivityCode()))) {
                message.append("补货活动ID无效");
                return;
            }
            List<String> activityProjectIds = Lists.newArrayList();
            for (ActivityInfoResponse activityInfoResponse : activityInfoResponses1) {
                Nullable.stream(activityInfoResponse.getActivityTermList()).forEach(it -> {
                    activityProjectIds.add(it.getActivityTermId());
                });
            }
            if (CollectionUtils.isEmpty(activityProjectIds)
                    || !activityProjectIds.contains(StringUtils.trim(forecastOrderDetailDTO.getActivityProjectCodeproject()))) {
                message.append("补货活动项目号无效");
            }
        }
    }

    private void validSubForecastOrder(ForecastOrderDTO forecastOrderDTO, List<ForecastOrderDetailDTO> orderLineToQueryActive, StringBuffer message, ForecastOrderDetailDTO forecastOrderDetailDTO, Set<String> scItemCodeSet) {
        //校验货品
        if (StringUtils.isBlank(forecastOrderDetailDTO.getScItemId())) {
            message.append("货品未填写");
            return;
        } else {
            scItemCodeSet.add(forecastOrderDetailDTO.getScItemId());
        }
        if (StringUtils.isBlank(forecastOrderDetailDTO.getSaleUnit())) {
            message.append("销售单位未填写");
            return;
        }
        //校验预报数量   不能为空，是数字，不能大于多少
        if (null == forecastOrderDetailDTO.getQuantity()) {
            message.append("数量未填写");
            return;
        }
        if (forecastOrderDetailDTO.getQuantity() <= 0 || forecastOrderDetailDTO.getQuantity() > 10000000) {
            message.append("预报数量应在0到10000000之间");
            return;
        }
        //校验备注信息   长度小于50
        if (StringUtils.isNotBlank(forecastOrderDetailDTO.getDetailRemark()) && forecastOrderDetailDTO.getDetailRemark().length() > 256) {
            message.append("备注详情信息长度不能超过255个字");
            return;
        }
        if (Objects.equals(forecastOrderDTO.getOrderType(), SaleOrderTag.REPLENISH_FORECAST.getCode())) {
            if (StringUtils.isBlank(forecastOrderDetailDTO.getActivityCode())) {
                message.append("补货活动ID必填");
                return;
            }
            if (StringUtils.isBlank(forecastOrderDetailDTO.getActivityProjectCodeproject())) {
                message.append("补货项目号必填");
                return;
            }
            if (StringUtils.isNotBlank(forecastOrderDetailDTO.getActivityCode()) &&
                    StringUtils.isNotBlank(forecastOrderDetailDTO.getActivityProjectCodeproject())) {
                orderLineToQueryActive.add(forecastOrderDetailDTO);
            }
        }
    }

    private void enrichCustomerAddressInfo(ForecastOrderSDO forecastOrderSDO, CustomerAddressSDO customerAddress) {
        forecastOrderSDO.setSaleChannelCode(customerAddress.getOrgSaleChannelCode());
        forecastOrderSDO.setSaleChannelName(customerAddress.getOrgSalesChannelName());
        forecastOrderSDO.setOrganizationCode(customerAddress.getOrgSaleOrganizationCode());
        forecastOrderSDO.setOrganizationName(customerAddress.getOrgSalesOrganizationName());
        forecastOrderSDO.setDepartmentCode(customerAddress.getOrgSaleDepartmentCode());
        forecastOrderSDO.setDepartmentName(customerAddress.getOrgSalesDepartmentName());
        forecastOrderSDO.setCustomerCode(customerAddress.getCustomerCode());
        forecastOrderSDO.setCustomerName(customerAddress.getCustomerName());
        forecastOrderSDO.setChannelCode(customerAddress.getChannelCode());
        forecastOrderSDO.setChannelName(customerAddress.getChannelName());
        forecastOrderSDO.setSalesmanCode(customerAddress.getPrincipal());
        forecastOrderSDO.setSalesmanName(customerAddress.getPrincipalName());
        forecastOrderSDO.setBisUnitCode(customerAddress.getOrgBussinessUnitCode());
        forecastOrderSDO.setReceiveDetailAddress(customerAddress.getAddressName());
        forecastOrderSDO.setReceiveAddressCode(customerAddress.getAddressCode());
        forecastOrderSDO.setContact(customerAddress.getContactName());
        forecastOrderSDO.setContactPhone(customerAddress.getCellphoneNumber());
        forecastOrderSDO.setVaildBeginTime(new Date());
    }

    private void validMainOrder(ForecastOrderDTO forecastOrderDTO, StringBuffer message) {
        List<String> typeList = Lists.newArrayList(SaleOrderTag.STD_FORECAST.getCode(), SaleOrderTag.CAR_FORECAST.getCode(), SaleOrderTag.REPLENISH_FORECAST.getCode());
        //sales organization out codes
//        Set<String> allSalesOrgCodes = getAllSalesOrgCodes();
        //预报订单类型校验
        if (StringUtils.isBlank(forecastOrderDTO.getOrderType())) {
            message.append("预报订单类型未填写");
            return;
        } else {
            if (!typeList.contains(forecastOrderDTO.getOrderType())) {
                message.append("订单类型无效");
                return;
            }
        }
        // 校验组织编码
        if (StringUtils.isBlank(forecastOrderDTO.getOrganizationCode())) {
            message.append("销售组织未填写");
            return;
        }
        //校验货品组信息
        if (StringUtils.isBlank(forecastOrderDTO.getProductGroupCode())) {
            message.append("货品组未填写");
            return;
        }
        //校验渠道编码
        if (StringUtils.isBlank(forecastOrderDTO.getChannelCode())) {
            message.append("业务渠道未填写");
            return;
        }

        if (StringUtils.isBlank(forecastOrderDTO.getReceiveAddressCode())) {
            message.append("客户送达方未填写");
            return;
        }
        // 校验组织编码
        if (StringUtils.isBlank(forecastOrderDTO.getFactoryCode())) {
            message.append("发货工厂未填写");
            return;
        }
        //校验货品组信息
        if (StringUtils.isBlank(forecastOrderDTO.getInventoryCode())) {
            message.append("库存地点编码未填写");
            return;
        }
        //校验渠道编码
        if (StringUtils.isBlank(forecastOrderDTO.getReferenceNo())) {
            message.append("外部订单号未填写");
            return;
        }

        //校验备注信息   长度小于50
        if (StringUtils.isNotBlank(forecastOrderDTO.getRemark()) && forecastOrderDTO.getRemark().length() > 256) {
            message.append("备注信息长度不能超过255个字");
            return;
        }

        //校验备注信息   长度小于30
        if (StringUtils.isNotBlank(forecastOrderDTO.getReferenceNo()) && forecastOrderDTO.getReferenceNo().length() > 30) {
            message.append("外部订单号长度不能超过30个字");
            return;
        }

        //预报子单不能为空
        if (CollectionUtils.isEmpty(forecastOrderDTO.getForecastOrderDetailDTOS())) {
            message.append("预报行项目不能为空");
        }

        //验证销售组织
//        if (!allSalesOrgCodes.contains(forecastOrderDTO.getOrganizationCode())){
//            message.append("销售组织不存在");
//        }

    }

    //补货订单查询活动信息
    private Map<String, List<ActivityInfoResponse>> activityQueryCodeSpec(ForecastOrderDTO forecastOrderDTO, List<ForecastOrderDetailDTO> lineList) {
        if (Objects.isNull(forecastOrderDTO) || CollectionUtils.isEmpty(lineList)) {
            return new HashMap<>();
        }
        // 只能根据逐个货品进行活动查询，多个货品的查询结果，无法匹配对应的货品 使用在进行补货活动，其他货品查询活动咨询峥嵘
        Map<String, List<ActivityInfoResponse>> stringListMap = new HashMap<>();
        QueryActivityRequest queryActivityRequest = new QueryActivityRequest();
        List<ActivityInfoRequest> activityInfoRequestList = Lists.newArrayList();
        for (ForecastOrderDetailDTO forecastOrder : lineList) {
            String customerExpectTDateStr = forecastOrderDTO.getExpectDeliveryDate();
            Date customerExpectTDate = new Date();
            //默认当天
            if (StringUtils.isBlank(customerExpectTDateStr)) {
                customerExpectTDate = new Date();
            } else {
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                try {
                    customerExpectTDate = simpleDateFormat.parse(customerExpectTDateStr);
                } catch (ParseException e) {
                    log.error("parse customerExpectTDate exception, detail: {}", JSON.toJSONString(forecastOrder));
                }
            }
            String s = UUIDUtil.newWithoutMinus();

            CustomerAddressRequest request = new CustomerAddressRequest();
            request.setAddressCode(forecastOrderDTO.getReceiveAddressCode());
            Result<CustomerAddressSDO> customerAddressSDOResult = customerAddressQueryService.queryCustomerAddressByShipAddressId(request);
            String clientId = "";
            if (customerAddressSDOResult.isSuccess() && Objects.nonNull(customerAddressSDOResult.getResult())) {
                clientId = customerAddressSDOResult.getResult().getCustomerCode();
            }

            String key = forecastOrderDTO.getReferenceNo() + forecastOrder.getScItemId();
            ActivityInfoRequest build = ActivityInfoRequest.builder()
                    //获取客户ID
                    .clientId(clientId) //客户编码
                    .activityUseTime(customerExpectTDate)
                    .deliveryDate(customerExpectTDate)
                    .mainOrderId(key)
                    .subOrderId("subOrder_" + s)
                    .salesOrganization(forecastOrderDTO.getOrganizationCode())
                    .businessChannel(forecastOrderDTO.getChannelCode())
                    .shipAddressId(forecastOrderDTO.getReceiveAddressCode()) //收货地址
                    .orderType(forecastOrderDTO.getOrderType()).build();
            List<ActivityItemInfoRequest> itemList = Lists.newArrayList();
            ActivityItemInfoRequest activityItemInfoRequest = ActivityItemInfoRequest
                    .builder().itemId(forecastOrder.getScItemId())
                    .salesUnit(forecastOrder.getSaleUnit())
                    .itemQuantity(new BigDecimal(forecastOrder.getQuantity()).longValue()).build();
            itemList.add(activityItemInfoRequest);
            build.setItemList(itemList);
            activityInfoRequestList.add(build);
        }
        queryActivityRequest.setActivityInfoRequestList(activityInfoRequestList);
        if (CollectionUtils.isNotEmpty(activityInfoRequestList)){
            Result<ActivityResponse> activityResponseResult = activityQueryService.batchQueryCanUsingActivity(queryActivityRequest);
            stringListMap = Nullable.stream(activityResponseResult.getResult().getActivityInfoResponseList()).collect(Collectors.groupingBy(ActivityInfoResponse::getMainOrderId));
        }
        return stringListMap;
    }


    @Override
    @FacadeInvoker
    public Result<Boolean> batchUpdateMainRemark(BatchUpdateMainRemarkRequest batchUpdateMainRemarkRequest){
        if (Objects.isNull(batchUpdateMainRemarkRequest)||CollectionUtils.isEmpty(batchUpdateMainRemarkRequest.getUpdateRequestList())){
            throw new FacadeException("请求参数不能为空");
        }
        for (BatchUpdateMainAddRemarkRequest updateMainRemarkRequest : batchUpdateMainRemarkRequest.getUpdateRequestList()) {
            BatchUpdateMainAddRemarkRequest batchUpdateMainAddRemarkRequest = new BatchUpdateMainAddRemarkRequest();
            batchUpdateMainAddRemarkRequest.setMainOrderId(updateMainRemarkRequest.getMainOrderId());
            batchUpdateMainAddRemarkRequest.setMainRemark(updateMainRemarkRequest.getMainRemark());
            batchUpdateMainAddRemarkRequest.setMainAddRemark(updateMainRemarkRequest.getMainAddRemark());
            batchUpdateMainAddRemarkRequest.setMainExpectDate(updateMainRemarkRequest.getMainExpectDate());
            forecastOrderService.updateForecastOrderRemark(batchUpdateMainAddRemarkRequest);
        }
        return Result.success(Boolean.TRUE);
    }


    /**
     * 导入去除空格
     * @param record
     * @param excludeFields
     */
    private void trim(Object record,List<String> excludeFields){
        if (record == null){
            return;
        }
        Field[] fields = record.getClass().getDeclaredFields();
        for (Field field : fields) {
            if (CollectionUtils.isNotEmpty(excludeFields) && excludeFields.contains(field.getName())){
                continue;
            }
            field.setAccessible(true);
            try {
                Object value = field.get(record);
                if (value instanceof String){
                    String str = (String) value;
                    field.set(record,str.trim());
                }
            } catch (Throwable e) {
                log.error("import_trim_error,fieldName:{}",field.getName(),e);
            }
        }
    }

    /**
     * 获取货品范围
     */
    private List<ScItemManageRange> searchScItemManageRange(){
        Result<List<ScItemManageRange>> search = scItemManageRangeReadService.searchWithPermission();
        return Optional.ofNullable(search).map(Result::getResult).orElse(null);
    }

    //校验货品经营范围
    private String checkScItemManageRange(List<ScItemManageRange> scItemManageRanges,String scItemCode){
        //判断是否全部禁用
        boolean allDisabled = scItemManageRanges.stream().allMatch(x -> ScItemManageRangeStatus.DISABLED.getValue().equals(x.getStatus()));
        if (allDisabled){
            return null;
        }
        //按销售组织分组
        Map<String, List<ScItemManageRange>> saleOrgId2RangeMap = scItemManageRanges.stream().collect(Collectors.groupingBy(ScItemManageRange::getSaleOrgId));
        if (saleOrgId2RangeMap.size() > 1){
            //移除掉某个组织全部禁用的
            saleOrgId2RangeMap.values().forEach(ranges->{
                boolean disabled = ranges.stream().allMatch(x -> ScItemManageRangeStatus.DISABLED.getValue().equals(x.getStatus()));
                if (disabled){
                    scItemManageRanges.removeAll(ranges);
                }
            });
        }
        List<ScItemManageRange> matchList = scItemManageRanges.stream().filter(x -> x.getScItemCode().equals(scItemCode)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(matchList)){
            return "不在分子公司经营货品范围内";
        }else {
            boolean enable = matchList.stream().anyMatch(range -> ScItemManageRangeStatus.ENABLE.getValue().equals(range.getStatus()));
            if (!enable){
                return "分子公司经营货品范围内为禁用状态";
            }
            return null;
        }
    }

}
